动态代理有不少种方式,如jdk代理,cglib,ASM等框架
在说动态代理以前先说一下静态代理ide
静态代理在使用时,须要定义接口或者父类,被代理对象和代理对象一块儿实现相同的接口或者继承相同的父类this
静态代理使用的是组合模式,在代理类中包含有被代理类的对象代理
public class TestStaticProxy { public static void main(String[] args) { NikeClothFactory nikeClothFactory = new NikeClothFactory(); ProxyFactory proxyFactory = new ProxyFactory(nikeClothFactory); proxyFactory.productCloth(); } } // 接口 interface ClothFactory{ void productCloth(); } // 被代理类 class NikeClothFactory implements ClothFactory{ @Override public void productCloth() { System.out.println("Nike工厂生产了一件Nike"); } } // 代理类 class ProxyFactory implements ClothFactory{ private ClothFactory clothFactory; public ProxyFactory(ClothFactory clothFactory){ this.clothFactory = clothFactory; } @Override public void productCloth() { System.out.println("代理类开始执行,准备调用被代理类"); clothFactory.productCloth(); } }
静态代理虽然能够在不修改目标对象功能的前提下对目标功能进行扩展,可是一旦接口增长方法,目标对象和代理类都要同时修改,并且代理对象和被代理对象要实现同样的接口,致使有不少的代理类,不便于维护code
jdk动态代理的底层是用的是java的反射,可是jdk代理的前提是目标类必须实现接口xml
使用步骤对象
核心方法为Proxy.newProxyInstance(ClassLoader,Class[],InvocationHandler)继承
三个参数分别表示接口
public class TestDynamicProxy { public static void main(String[] args) { RealSubject realSubject = new RealSubject(); MyInvationHandler myInvationHandler = new MyInvationHandler(); Object obj = myInvationHandler.blind(realSubject); Subject sub = (Subject) obj; sub.action(); } } // 接口 interface Subject{ void action(); } // 真正执行的方法,被代理类 class RealSubject implements Subject{ @Override public void action() { System.out.println("被代理类开始执行"); } } class MyInvationHandler implements InvocationHandler{ // 实现了接口的被代理类的对象的声明 Object obj; // 被代理类的实例 // 返回一个代理类的对象 public Object blind(Object obj){ this.obj = obj; // ①使用被代理类的类加载器②被代理类的接口③代理类的实例 return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this); } /** * 当经过代理类的对象被重写的方法调用时,都会转换为对invoke方法的调用 * @param proxy 正在返回的代理对象,通常状况下,在invoke方法中不使用该对象 * @param method 正在被调用的方法 * @param args 调用方法时,传入的参数 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(obj,args); } }
静态代理和jdk动态代理都妖气目标对象必定要实现接口,可是有时候目标对象只是一个单独的对象,并无实现任何接口,这个时候采用以目标对象子类的方式实现代理,该方法称为cglib代理
Cglib包的底层是经过使用一个字节码处理框架ASM来转换字节码并生成新的类,因为要生成子类,因此要被代理的类不能够被final修饰
须要引入cglib的包
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency>
使用步骤
public class CglibProxy implements MethodInterceptor { public Object getProxy(Class clazz){ Enhancer enhancer = new Enhancer(); // 指定代理类的父类 enhancer.setSuperclass(clazz); // 设置Callback对象 enhancer.setCallback(this); // 经过字节码技术动态建立子类实例 return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("前置处理"); // 调用MethodProxy.invokeSuper方法将调用转发给原始对象 Object result = methodProxy.invokeSuper(o,objects); System.out.println("后置处理"); return result; } } public class Test { public void print(){ System.out.println("方法执行"); } public static void main(String[] args) { CglibProxy proxy = new CglibProxy(); Test proxyImp = (Test) proxy.getProxy(Test.class); proxyImp.print(); } }
因为自己的博客百度没有收录,博客地址http://zhhll.icu