网站收录了没有排名,南京网站建设 雷仁网络,网站建设方案计划书人员规划,网站群 意义目录
1. 代理模式
2. 静态代理
3. 动态代理
3.1 JDK 动态代理
3.2 CGLIB 动态代理
4. JDK 动态代理和 CGLIB 动态代理对比
5. Spring代理选择
6. Spring AOP 实现原理
6.1 织入
7. JDK 动态代理实现
8. CGLIB 动态代理实现
9. 总结 1. 代理模式 代理模式#xf…目录
1. 代理模式
2. 静态代理
3. 动态代理
3.1 JDK 动态代理
3.2 CGLIB 动态代理
4. JDK 动态代理和 CGLIB 动态代理对比
5. Spring代理选择
6. Spring AOP 实现原理
6.1 织入
7. JDK 动态代理实现
8. CGLIB 动态代理实现
9. 总结 1. 代理模式 代理模式为其他对象提供⼀种 代理 以控制对这个对象的访问。在某些情况下一个对象不适合或者不能直接引用另⼀个对象而代理对象可以在客户端和目标对象之间起到中介的作用。 代理模式分为静态代理和动态代理。
2. 静态代理 静态代理中我们对目标对象的每个方法的增强都是手动完成的非常不灵活比如接口⼀旦新增加方法目标对象和代理对象都要进行修改且麻烦需要对每个目标类都单独写⼀个代理类。 实际应用场景非常少日常开发几乎看不到使用静态代理的场景。 上面我们是从实现和应用角度来说的静态代理从 JVM 层面来说 静态代理在编译时就将接⼝、实现类、代理类这些都变成了⼀个个实际的 class 文件 。 静态代理实现步骤 定义⼀个接口及其实现类 创建⼀个代理类同样 实现这个接口 将目标对象注入进代理类然后在代理类的对应方法调用目标类中的对应方法。
这样我们就可以通过代理类屏蔽目标对象的访问并且可以在目标方法执行前后实现其他的功能。接下来我们来看一下具体是如何实现静态代理的
1. 定义接口 2. 实现接口 3. 创建代理类并同样实现支付接口 4. 实际使用 3. 动态代理
相比于静态代理来说动态代理更加灵活。我们不需要针对每个目标类都单独创建一个代理类并且也不需要我们必须实现接口我们可以直接代理实现类( CGLIB 动态代理机制)。 从 JVM 角度来说动态代理是在运行时动态生成类字节码并加载到 JVM 中 的。 Spring AOP 的实现依赖了动态代理。 就 Java 来说动态代理的实现方式有很多种比如 JDK 动态代理、CGLIB 动态代理等等。 3.1 JDK 动态代理 在 Java 动态代理机制中 InvocationHandler 接口 和 Proxy 类 是核心。 JDK 动态代理类步骤 定义⼀个接口及其实现类 自定义 InvocationHandler 并重写 invoke 方法 在 invoke 方法中会调用原生方法被代理类的方法并自定义⼀些处理逻辑 通过 Proxy.newProxyInstance(ClassLoader loader,Class?[] interfaces,InvocationHandler h) 方法创建代理对象
定义 JDK 动态代理类 创建一个代理对象并使用 Proxy 类中使用频率最高的方法是newProxyInstance() 这个方法主要用来生成⼀个代理对象。 这个方法⼀共有 3 个参数 loader :类加载器用于加载代理对象。 interfaces : 被代理类实现的⼀些接口 h : 实现了 InvocationHandler 接口的对象
3.2 CGLIB 动态代理 JDK 动态代理有⼀个最致命的问题是其只能代理实现了接口的类。 因此可以通过 CGLIB 动态代理机制来避免。 CGLIB(Code Generation Library)是⼀个基于 ASM 的字节码生成库它允许我们在运行时对字节码进行修改和动态生成。CGLIB 通过继承方式实现代理。很多知 名的开源框架都使用到 CGLIB例如 Spring 的 AOP 模块中如果目标对象 实现了接口 则默认采用 JDK 动态代理否则采用 CGLIB 动态代理。 在 CGLIB 动态代理机制中 MethodInterceptor 接口 和 Enhancer 类 是核心。 CGLIB 动态代理类使用步骤
定义⼀个类 ⾃定义 MethodInterceptor 并重写 intercept 方法intercept 用于拦截增强被代理类的方法和 JDK 动态代理中的 invoke 方法类似 通过 Enhancer 类的 create()创建代理类。
添加依赖 和JDK 动态代理不同, CGLIB(Code Generation Library) 实际是属于⼀个开源项目使用时需要手动添加相关依赖。 dependencygroupIdcglib/groupIdartifactIdcglib/artifactIdversion3.3.0/version
/dependency
自定义 MethodInterceptor方法拦截器 创建代理类, 并使用 自定义 MethodInterceptor 并重写 intercept 方法 intercept 用于拦截增强被代理类的方法 obj : 被代理的对象需要增强的对象 method : 被拦截的方法需要增强的方法 args : 方法入参 proxy : 用于调用原始方法 4. JDK 动态代理和 CGLIB 动态代理对比 JDK 动态代理只能代理实现了接口的类或者直接代理接口而 CGLIB 可以代理未实现任何接口的类。 CGLIB 动态代理是通过生成⼀个被代理类的子类来拦截被代理类的方法调用因此不能代理声明为 final。 性能: 大 部分情况都是 JDK 动态代理更优秀随着 JDK 版本的升级这个优势更加明显。 5. Spring代理选择 proxyTargetClass 为 false, 目标实现了接口, 用 jdk 代理 proxyTargetClass 为 false, 目标未实现接口, 用 cglib代理 proxyTargetClass 为 true, 用 cglib 代理
6. Spring AOP 实现原理 Spring AOP 是构建在动态代理基础上因此 Spring 对 AOP 的支持局限于方法级别的拦截。 Spring AOP 支持 JDK Proxy 和 CGLIB 方式实现动态代理。默认情况下 实现了接口的类使 用 AOP 会基于 JDK 生成代理类没有实现接口的类会基于 CGLIB 生成代理类。 6.1 织入 织入是把切面应用到目标对象并创建新的代理对象的过程切面在指定的连接点被织入到目标对 象中。 在目标对象的生命周期里有多个点可以进行织入 编译期切⾯在⽬标类编译时被织⼊。这种⽅式需要特殊的编译器。AspectJ的织⼊编译器就 是以这种⽅式织⼊切⾯的。 类加载期切⾯在⽬标类加载到JVM时被织⼊。这种⽅式需要特殊的类加载器 ClassLoader,它可以在⽬标类被引⼊应⽤之前增强该⽬标类的字节码。AspectJ5的加载 时织⼊load-time weaving. LTW就⽀持以这种⽅式织⼊切⾯。 运行期切面在应用运行的某一时刻被织入。一般情况下在织入切面时AOP 容器会为目标对象动态创建一个代理对象。Spring AOP 就是以这种方式织入切面的。
7. JDK 动态代理实现
public interface PayService {void pay();
}
public class AliPayService implements PayService{Overridepublic void pay(){System.out.println(ali pay...);}
}
public class PayServiceJDKInvocationHandler implements InvocationHandler {// 目标对象就是被代理对象private Object target;public PayServiceJDKInvocationHandler(Object target) {this.target target;}Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(安全检查);System.out.println(记录日志);System.out.println(记录开始时间);// 通过反射调用被代理的方法Object retVal method.invoke(target,args);System.out.println(记录结束时间);return retVal;}public static void main(String[] args) {PayService target new AliPayService();// 方法调用处理器InvocationHandler handler new PayServiceJDKInvocationHandler(target);// 创建一个代理类通过被代理类、被代理实现的接口、方法调用处理器来创建PayService proxy (PayService) Proxy.newProxyInstance(target.getClass().getClassLoader(),new Class[]{PayService.class},handler);proxy.pay();}
}8. CGLIB 动态代理实现
public interface PayService {void pay();
}
public class PayServiceCGLIBInterceptor implements MethodInterceptor {// 被代理对象private Object target;public PayServiceCGLIBInterceptor(Object target) {this.target target;}Overridepublic Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println(安全检查);System.out.println(记录日志);System.out.println(记录开始时间);// 通过反射调用被代理的方法Object retVal methodProxy.invoke(target,args);System.out.println(记录结束时间);return retVal;}public static void main(String[] args) {PayService target new AliPayService();PayService proxy (PayService) Enhancer.create(target.getClass(),new PayServiceCGLIBInterceptor(target));proxy.pay();}
}9. 总结 AOP 是对某方面能力的统⼀实现它是⼀种实现思想Spring AOP 是对 AOP 的具体实现Spring AOP 可通过 AspectJ注解的方式来实现 AOP 的功能Spring AOP 的实现步骤是 添加 AOP 框架支持定义切面和切点定义通知。 Spring AOP 是通过动态代理的方式在运行期将 AOP 代码织入到程序中的它的实现方式有两种 JDK Proxy 和 CGLIB。