Java的代理模式
分为静态代理和动态代理。在客户类不能或不想直接引用委托类代理类可以起到中介的作用。类似于我想买车但我不想去做市场调查学习车配置知识以及购车后的办证交税等一系列行为那我可以委托中介。这个中介就是代理类买车这件事则是委托类。代理模式符合代码的开闭原则可以增加委托类的功能。例如买车事件中中介可以帮我在买车前收集各种车辆信息做对比买车后帮我办行驶证和缴纳购置税。这就是买车的额外功能。放在代码上可以是给业务类实现缓存、日志等功能。静态代理直接用代码创建或者使用工具生成源代码然后编译。在程序运行之前代理类.class已经创建。动态代理在程序运行时通过反射动态创建。静态代理写一个服务接口买车实现服务接口的服务类买车创建代理类买车中间代理类实现服务接口重写买车方法在买车方法内写好买车前的准备然后调用服务类的买车方法最后写买车后的行为。优点符合开闭原则对目标类进行功能扩展。缺点每一个目标类都需要创建一个代理类工作量大不易管理。接口改变代理类也要变。动态代理不需要手动创建代理类只需要编写一个动态处理器即可。JDK动态代理创建服务类接口实现服务接口编写动态处理器。代理对象会在JDK运行时动态创建。public class DynamicProxyHandler implements InvocationHandler { private Object object; public DynamicProxyHandler(final Object object) { this.objectobject; } Override public Object invoke(Object proxy, Method method,Object[] args) throws Throwable { System.out.println(买车前准备); Object result method.invoke(object,args); System.out.println(买车后购置税); return result; } }调用BuyCar buyCar new BuyCarImpl(); BuyCar proxyBuyCar (BuyCar) Proxy.newProxyInstance( BuyCar.class.getClassLoader(), new Class[]{BuyCar.class}, new DynamicProxyHandler(buyCar) ); proxyBuyCar.buyCar();Proxy是所有动态生成代理的共同父类这个类有一个静态方法Proxy.newProxyInstance()调用时动态创建代理类接受三个参数·ClassLoader loader指定当前目标对象的类加载器获得加载器的方法是固定的·Class?[] interfaces指定目标对象实现的接口类型可以多个所以用数组用泛型确认类型。·InvocationHandler指定动态处理器如上述实现InvocationHandler接口的类调用代理对象时会执行动态处理器中的invoke方法。优点相比静态代理JDK动态代理无需创建为每个服务类创建代理类只需要调用时使用Proxy类动态生成代理类。缺点Proxy是所有动态生成的代理类共同的父类Java不支持多继承只能通过接口的形式实现。JDK动态代理生成的代理类强制继承了java.lang.reflect.Proxy类所以无法继承目标业务类所以只能通过实现目标业务类的接口来间接代理。CGLib动态代理对于没有接口的类就不适用JDK动态代理了。CGLib采用字节码技术通过底层字节码创建一个子类并在子类中采用拦截的方式拦截所有父类方法的调用再插入拦截逻辑。因为需要创建子类所以不能使用final修饰的类进行代理final修饰的类无法被继承。JDK动态代理和CGLib动态代理是实现Spring AOP的基础。创建服务类类不是接口public class BuyCar2 { public void buyCar() { System.out.println(我要买车); } }创建CGLib代理类public class CgLibProxy implements MethodInterceptor { private Object target; public CgLibProxy(Object target) { this.target target; } public Object getProxyInstance(){ Enhancer enhancer new Enhancer();//工具类 enhancer.setSuperclass(target.getClass());//设置父类 enhancer.setCallback(this);//设置回调函数 return enhancer.create();//创建子类代理对象 } public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println(买车前准备); Object result method.invoke(target,args); System.out.println(买车后购置税); return result; } }最后调用BuyCar2 target new BuyCar2(); CgLibProxy cgLibProxy new CgLibProxy(target); BuyCar2 buyCarCglibProxy (BuyCar2) cgLibProxy.getProxyInstance(); buyCarCglibProxy.buyCar();