设计模式(三)
代理模式
扩展目标对象的功能
-
静态代理
每一个代理类都必须实现一遍委托类的接口,如果接口增加方法,则代理类也跟着修改,违背“开闭原则”
-
动态代理
-
jdk动态代理
public interface Subject { //委托类的接口 void sysHello(); } public class RealSubject implements Subject{ //真正的委托类 @Override public void sysHello() { System.out.println("hello world"); } } public class MyProxy implements InvocationHandler {// 用户代理类 public Object object; public MyProxy(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { pre(); Object invoke = method.invoke(object, args); post(); return invoke; } private void pre(){ System.out.println("方法执行之前************************"); } private void post(){ System.out.println("方法执行之后************************"); } } public class Client { public static void main(String[] args) { Subject subject = new RealSubject(); MyProxy myProxy = new MyProxy(subject); ClassLoader loader = subject.getClass().getClassLoader(); Class<?>[] interfaces = subject.getClass().getInterfaces(); Subject s = (Subject)Proxy.newProxyInstance(loader, interfaces, myProxy); s.sysHello(); } }类加载器、接口数组可以理解为一个方法树,后面 s.sysHello();来告诉jvm方法树上的哪个方法。
classLoader 将字节码文件加载进虚拟机并生成相应的class
总结:
- 动态代理程序运行时,通过反射机制动态生成的
- 一般代理接口下所有的类
-
cglib动态代理
-
首先导入 CGLIB 相关 jar 包
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.4</version> </dependency> -
创建真实角色
public class RealSubject { public void request() { System.out.println("真实角色"); } } -
创建一个自定义方法拦截器,这个自定义方法拦截器实现了拦截器类
public class MyMethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { rep(); Object o1 = methodProxy.invokeSuper(o, objects); post(); return o1 ; } public void rep(){ System.out.println("方法之前。。。。。。。。。。。。。"); } public void post(){ System.out.println("方法之后。。。。。。。。。。。。。"); } }Object obj: obj 是 CGLIB 动态生成代理类实例
Method method: Method 为实体类所调用的被代理的方法引用
Objectp[] args: 这个就是方法的参数列表
MethodProxy methodProxy : 这个就是生成的代理类对方法的引用。
-
测试类
public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(RealSubject.class); enhancer.setCallback(new MyMethodInterceptor()); RealSubject proxy = (RealSubject) enhancer.create(); proxy.request(); }
原理: CGLIB是⼀个强⼤的⾼性能的代码⽣成包,底层是通过使⽤⼀个⼩⽽快的字节码处理框架ASM,它可以在 运⾏期扩展Java类与实现Java接
Enhancer是CGLIB的字节码增强器,可以很⽅便的对类进⾏拓展
创建代理对象的⼏个步骤:
1、⽣成代理类的⼆进制字节码⽂件
2、加载⼆进制字节码,⽣成Class对象( 例如使⽤Class.forName()⽅法 )
3、通过反射机制获得实例构造,并创建代理类对象
总结
jdk动态代理:利⽤拦截器(拦截器必须实现InvocationHanlder)加上反射机制⽣成⼀个实现代理接⼝的 匿名类,在调⽤具体⽅法前调⽤InvokeHandler来处理。只能对实现了接⼝的类⽣成代理只能对实现了 接⼝的类⽣成代理
cglib:利⽤ASM开源包,对代理对象类的class⽂件加载进来,通过修改其字节码⽣成⼦类来处理。主要是对指定的类⽣成⼀个⼦类,覆盖其中的⽅法,并覆盖其中⽅法实现增强,但是因为采⽤的是继承, 对于final类或⽅法,是⽆法继承的。
选择
a. 如果⽬标对象实现了接⼝,默认情况下会采⽤JDK的动态代理实现AOP。
b. 如果⽬标对象实现了接⼝,可以强制使⽤CGLIB实现AOP。
c. 如果⽬标对象没有实现了接⼝,必须采⽤CGLIB库,Spring会⾃动在JDK动态代理和CGLIB之间转 换。
-
-

浙公网安备 33010602011771号