当前位置: 首页 > news >正文

青岛做外贸网站哪家好纯flash网站下载

青岛做外贸网站哪家好,纯flash网站下载,网站管理建设工作,如何销售做网站文章目录 一、定义二、静态代理三、动态代理1. JDK代理1.1 JDK代理实现流程1.2 动态生成的类字节码 2. Cglib代理2.1 Cglib实现流程 四、总结 一、定义 静态代理和动态代理都反映了一个代理模式#xff0c;代理模式是一种经典的设计模式#xff0c;常用于为其他对象提供一种… 文章目录 一、定义二、静态代理三、动态代理1. JDK代理1.1 JDK代理实现流程1.2 动态生成的类字节码 2. Cglib代理2.1 Cglib实现流程 四、总结 一、定义 静态代理和动态代理都反映了一个代理模式代理模式是一种经典的设计模式常用于为其他对象提供一种代理或占位符以限制对它的访问充当访问对象的中介。 就好比平时我们租房会和中介进行沟通中介带我们去看房中介又与房东保持联系但房东不会带我们看房。 二、静态代理 静态代理是一种代理模式的实现静态代理在编译时就确定了代理类和目标类之间的关系。 在静态代理中代理类和目标类通常实现相同的接口或者代理类继承目标类。 代理类作为目标类的包装持有目标类的引用并且调用目标对象的方法前后进行增强操作。 下面举个例子 public interface Landlord {/*** 出租房间*/void rentingHouse();}public class ShenZhenLandlord implements Landlord {Overridepublic void rentingHouse() {System.out.println(深圳房东出租房间);} }public class Intermediary implements Landlord{/*** 代理类*/private final Landlord landlord;public Intermediary(Landlord landlord) {this.landlord landlord;}Overridepublic void rentingHouse() {System.out.println(中介带租客看房);landlord.rentingHouse();System.out.println(中介收取出租非);} }public static void main(String[] args) {// 目标类Landlord landlord new ShenZhenLandlord();//代理类Intermediary intermediary new Intermediary(landlord);// 运行代理方法intermediary.rentingHouse(); }这是一个经典的代理模式的实现可以在不修改原对象的情况下对目标类进行增强处理但是若接口新增方法所有代理类都都需要新增对应的实现不好维护。 三、动态代理 动态代理是一个在运行期间动态创建代理对象的技术它允许开发者为一个或多个接口创建一个代理对象且无需事先知道具体实现类。 静态代理和动态代理的区别在于class文件是编译期间确定还是运行期间确定 静态代理在编写代码的时候就明确了代理类和目标类之间的关系在编译阶段会生成一个Class对象。 动态代理则是在运行阶段动态生成代理对象在运行的时候动态生成字节码并加载到JVM中去 1. JDK代理 JDK代理技术是Java提供的一种动态代理技术使用方式如下 public class ProxyFactory {/*** 目标类*/private Object target;public ProxyFactory(Object target) {this.target target;}public Object getProxyInstance() {return Proxy.newProxyInstance(// 目标类加载器target.getClass().getClassLoader(),// 目标对象的接口类型target.getClass().getInterfaces(),// 事件处理new InvocationHandler() {Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(前置增强);method.invoke(target, args);System.out.println(后置增强);return null;}});} }public static void main(String[] args) {ShenZhenLandlord landlord new ShenZhenLandlord();System.out.println(landlord.getClass());Landlord proxyInstance (Landlord) new ProxyFactory(landlord).getProxyInstance();proxyInstance.rentingHouse();System.out.println(proxyInstance.getClass()); }代理类打印出的Class为com.sun.proxy.$Proxy0, 从ShenZhenLandlord到 com.sun.proxy.$Proxy0 其中经历了什么呢 1.1 JDK代理实现流程 需要知道的是JVM虚拟机的类加载过程分为加载、验证、准备、解析、初始化这五个阶段 在加载阶段需要进行下面这几个步骤 通过一个类的全限定名获取定义此类的二进制字节流将这个字节流所代表的静态结构转化为方法区的运行时数据结构内存生成一个代表这类的Class对象作为方法区这个类的各种数据访问入口 而获取类的二进制字节流JVM提供了三种途径 本地获取字节码比如前面的ShenZhenLandlord类编译后就属于本地的字节码从网络中获取可以使用URLClassLoader来加载类运行时计算生成在程序运行的过程中动态生成类字节码 而代理就是运行时动态生成字节码然后交给JVM进行类加载过程使用。 所以经过JDK代理后从ShenZhenLandlord变成了com.sun.proxy.$Proxy0也就是程序在运行中通过计算生成了$Proxy0代理类的类字节码。 1.2 动态生成的类字节码 由于动态生成的类字节码是动态计算出来并加载到JVM内存中去因此无法通过查看编译后的文件去查看这个代理类的 Class文件。 不过可以通过arthas工具来查看动态生成的类字节码。 下载官网https://arthas.aliyun.com/doc/download.html#%E7%94%A8-arthas-boot-%E5%90%AF%E5%8A%A8 输入命令java -jar arthas-boot.jar 运行arthas proxy.jdk.Main 就是我们要查看的目标类按3进入监控界面如下图所示就代表进入成功了 输入命令jad com.sun.proxy.$Proxy0命令就能解析出$Proxy0的源码了 整理一下代码如下 public final class $Proxy0 extends Proxy implements Landlord {private static Method m1;private static Method m3;private static Method m2;private static Method m0;// 构造参数为InvocationHandlerpublic $Proxy0(InvocationHandler invocationHandler) {super(invocationHandler);}static {try {m3 Class.forName(proxy.static_proxy.Landlord).getMethod(rentingHouse, new Class[0]);return;}catch (NoSuchMethodException noSuchMethodException) {throw new NoSuchMethodError(noSuchMethodException.getMessage());}catch (ClassNotFoundException classNotFoundException) {throw new NoClassDefFoundError(classNotFoundException.getMessage());}}// Landlord接口的rentingHouse方法public final void rentingHouse() {try {this.h.invoke(this, m3, null);return;}catch (Error | RuntimeException throwable) {throw throwable;}catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);}} }看一个类首先先看构造方法KaTeX parse error: Expected EOF, got # at position 70: …就是ProxyFactory#̲getProxyInstanc…Proxy0的构造方法传进去的也就是是同一个 public Object getProxyInstance() {return Proxy.newProxyInstance(// 目标类加载器target.getClass().getClassLoader(),// 目标对象的接口类型target.getClass().getInterfaces(),// 事件处理new InvocationHandler() {Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(前置增强);method.invoke(target, args);System.out.println(后置增强);return null;}});}我们稍微看一下Proxy的源码 private static final Class?[] constructorParams { InvocationHandler.class };public static Object newProxyInstance(ClassLoader loader,Class?[] interfaces,InvocationHandler h) throws IllegalArgumentException {final Class?[] intfs interfaces.clone();/** 获取动态生成的字节码*/Class? cl getProxyClass0(loader, intfs);/** 获取这个代理类的构造参数为InvocationHandler的构造方法*/final Constructor? cons cl.getConstructor(constructorParams);final InvocationHandler ih h;if (!Modifier.isPublic(cl.getModifiers())) {AccessController.doPrivileged(new PrivilegedActionVoid() {public Void run() {cons.setAccessible(true);return null;}});}// 将h作为构造参数创建代理类return cons.newInstance(new Object[]{h}); }那么在$Proxy0#rentingHouse方法调用了构造参数传进来的InvocationHandler的invoke方法也就是调用了下面这个方法增强后的方法 new InvocationHandler() {Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(前置增强);method.invoke(target, args);System.out.println(后置增强);return null;} }通过这就可以得出下面的结论 代理类实际上就是实现了Landlord接口重写了rentingHouse方法当外界调用代理类的rentingHouse方法的时候实际上就是调用了new InvocationHandler的invoke方法 2. Cglib代理 CglibCode Generation Library是一个强大的高性能代码生成库用于在运行时扩展Java类和实现接口。它通过字节码技术动态生成新的类从而实现对目标类的代理。Cglib代理是AOP面向切面编程中常用的一种代理方式尤其是在需要代理那些没有实现接口的类时。 举个例子 目标类如下 public class UserServiceImpl {public String selectList(){System.out.println(正在查询);return 小明, 小红, 小黄;} }public class UserLogProxy implements MethodInterceptor {/*** 生成 CGLIB 动态代理类方法** param target* return*/public Object getLogProxy(Object target) {// 增强器类用来创建动态代理类Enhancer enhancer new Enhancer();// 设置代理类的父类字节码对象enhancer.setSuperclass(target.getClass());// 设置回调enhancer.setCallback(this);// 创建动态代理对象并返回return enhancer.create();}Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println(开始查询);// 执行原始方法Object result methodProxy.invokeSuper(o, objects);System.out.println(查询完毕);return result;} }public class MethodProxy{public Object invokeSuper(Object obj, Object[] args) throws Throwable {try {init();FastClassInfo fci fastClassInfo;return fci.f2.invoke(fci.i2, obj, args);} catch (InvocationTargetException e) {throw e.getTargetException();}} }public class Main {public static void main(String[] args) {// 目标对象UserServiceImpl userService new UserServiceImpl();System.out.println(userService.getClass());// 代理对象UserServiceImpl proxy (UserServiceImpl) new UserLogProxy().getLogProxy(userService);System.out.println(proxy.getClass());String userList proxy.selectList();System.out.println(userList);while (true) {}} }2.1 Cglib实现流程 使用arthas工具将proxy.cglib.UserServiceImpl$$EnhancerByCGLIB$$b96d19a3类的代码获取出来。 public class UserServiceImpl$$EnhancerByCGLIB$$b96d19a3 extends UserServiceImpl implements Factory {private MethodInterceptor CGLIB$CALLBACK_0;public final String selectList() {// 是否设置了回调MethodInterceptor methodInterceptor this.CGLIB$CALLBACK_0;if (methodInterceptor null) {UserServiceImpl$$EnhancerByCGLIB$$b96d19a3.CGLIB$BIND_CALLBACKS(this);methodInterceptor this.CGLIB$CALLBACK_0;}// 设置回调需要调用 intercept 方法if (methodInterceptor ! null) {return (String)methodInterceptor.intercept(this, CGLIB$selectList$0$Method, CGLIB$emptyArgs, CGLIB$selectList$0$Proxy);}// 无回调调用父类的 findUserList 即可return super.selectList();}}在JVM编译阶段Enhancer会根据目标类信息去动态生成代理类并设置回调。 当用户通过Cglib动态代理执行selectList方法的时候会直接调用methodInterceptor.intercept方法在intercept方法中通过invikeSuper调用父类的selectList方法。 如果没有设置回调则直接调用父类的selectList方法。 四、总结 JDK代理与Cglib代理对比 Cglib实现的动态代理是基于ASM字节码生成框架实现的使用字节码技术生成代理类在JDK1.6之前比使用Java反射效率要高一点。但是需要注意Cglib代理技术不可对final类进行类或方法的代理因为Cglib的原理是动态生成代理类的子类实现的。在JDK1.6以后的版本已经开始对JDK代理进行优化具体优化了什么 以后有机会再写篇文章讲在调用次数较少的情况JDK代理的效率要比Cglib代理效率要高只有进行大量调用的时候Cglib的优势才会出现。而到了JDK1.8JDK代理的效率已经高于Cglib代理因此在有接口的情况下推荐优先使用JDK代理没接口优先推荐使用Cglib代理技术。 动态代理与静态代理的比较 动态代理的最大优势就是在于可以把接口中声明的所有方法转移到调用处理器的一个集中的方法进行处理(Invocation.invoke)在接口数量比较多的情况下可以进行灵活处理。如果接口增加一个方法静态代理模式除了所有实现类需要实现这个方法外所有代理类也需要实现此方法。增加了代码维护的复杂度。而动态代理不会出现该问题
http://www.tj-hxxt.cn/news/228797.html

相关文章:

  • 广州专业制作网站网络推广策略概念
  • 电子商务网站建设详细策划书怎么做宣传网页
  • 网站后台编辑框无法显示苏州建设局网站实名制
  • 南昌餐厅网站建设聊城专业网站制作公司
  • 做网站需要掌握什么相册特效手机网站
  • 星河东莞网站建设一个完整的网址包含哪些内容
  • 什么网站做博客好私人免费网站怎么下载
  • 小游戏网站欣赏做网站都需要做什么
  • 做影视网站关停绵阳网站托管
  • 网站建设合同内容seo如何优化网站
  • 做百度快照要先有网站吗做苗木选择哪个网站
  • 邢台优化网站排名网站建设财务怎么入账
  • 网站排名logo怎么做广州越秀区是不是中风险地区
  • 商务网站建设的步骤商业网络平台
  • 做网站这个工作怎么样网站建设的风险预测
  • 厦门网站建设哪家好厦门最好的网站建设如何微信做演讲视频网站
  • 外贸平台有哪些小网站开一家代做网站的公司
  • 网站内链符号汽车网站 源码
  • 如何做全球网站排名网络营销措施有哪些
  • 做酒店销售上哪个网站好编程训练网站
  • 在哪些网站做外贸好七牛云域名
  • 导购网站模板免费下载google推广妙招
  • 网站与服务器的关系网站的推广费用票可以做抵扣吗
  • win10建设网站目录欧美网站建设公司排名
  • 旅游网站建设的技术方案滨州正规网站建设公司
  • 旅游资讯网站建设方案公司制做网站
  • 哪个网站可以查企业信息网站必须做电子认证吗
  • 做班级网站的实训报告如何做网站的版块规划
  • 怎样查找网站域名辽宁省住房和城乡建设网站
  • 网站建设推广邮件应用小程序下载