介绍 什么是代理模式 静态代理 JDK 自带的动态代理 CGLIB 动态代理 代理模式 意图:为其他对象提供一种代理,以控制对这个对象的访问。
例子:买火车票不一定要在火车站,去网上各个代理商那里也可以
代码思路:实体类 A 实现了接口 IA,而实体类 A 很复杂,那么使用实体类 B 去实现接口 IA,通过实体类 B 调用实体类 A 去满足功能。
注意事项:
1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。
2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。
静态代理 静态代理其实就是在程序运行之前,提前写好被代理方法的代理类,编译后运行。
下面代理模式实现需要写很多代码,不建议使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 // 接口 A public interface IServiceA { void sayHello(String str); } // ServiceAImpl 实现接口 A public class ServiceAImpl implements IServiceA { @Override public void sayHello(String str) { System.out.println(str); } } // 代理对象 ServiceProxyAImpl 也实现接口 A,并且构造函数必须传入接口 A 的实例 public class ServiceProxyAImpl implements IServiceA { private IServiceA iServiceA; public ServiceProxyAImpl(IServiceA iServiceA) { this.iServiceA = iServiceA; } @Override public void sayHello(String str) { iServiceA.sayHello(str+ " is proxy "); } } // 进行测试 public class Main { public static void main(String[] args) { IServiceA realA = new ServiceAImpl(); // 传入真实对象 IServiceA proxyA = new ServiceProxyAImpl(realA); realA.sayHello("realA"); // 代理对象的调用 proxyA.sayHello("proxyA"); } } 程序输出 : ServiceAImpl sayrealA ServiceAImpl sayproxyA is proxy
动态代理 通过反射机制,在运行时生成代理类
JDK 动态代理 被代理的类需要是接口实现 ,如果被代理的类没有实现接口,就不能使用 JDK 动态代理
java.lang.reflect.Proxy:生成动态代理类和对象; java.lang.reflect.InvocationHandler:通过 invoke 方法实现对真实角色的代理访问。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 // 接口 A public interface IServiceA { void sayHello(String str); } // ServiceAImpl 实现接口 A public class ServiceAImpl implements IServiceA { @Override public void sayHello(String str) { System.out.println(str); } } public class ProxyHandler implements InvocationHandler { private IServiceA serviceA; public ProxyHandler(IServiceA serviceA) { this.serviceA = serviceA; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(serviceA, args); } } public class MainProxy { public static void main(String[] args) { // 真实对象 IServiceA serviceA = new ServiceAImpl(); // 通过 Proxy 得到代理对象 IServiceA proxyServiceA = (IServiceA) Proxy .newProxyInstance(serviceA.getClass().getClassLoader(), serviceA.getClass().getInterfaces(), new ProxyHandler(serviceA)); serviceA.sayHello("serviceA"); proxyServiceA.sayHello("proxy serviceA"); } } 程序输出: serviceA proxy serviceA
CGLIB 动态代理 通过改变字节码,对需要被代理的类,生成他的子类,子类去覆盖被代理类的方法 ,其中 private、final 修饰的方法不会被重写。
首先实现 MethodInterceptor,方法调用会被转发到该类的 intercept() 方法。 通过 Enhancer 来指定要代理的目标对象、实际处理代理逻辑的对象,最终通过调用 create() 方法得到代理对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 // 接口 A public interface IServiceA { void sayHello(String str); } // ServiceAImpl 实现接口 A public class ServiceAImpl implements IServiceA { @Override public void sayHello(String str) { System.out.println(str); } } public class MyMethodInterceptor implements MethodInterceptor { public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { return methodProxy.invokeSuper(o,objects); } } public class CGLIBMain { public static void main(String[] args) { IServiceA serviceA = new ServiceAImpl(); serviceA.sayHello("serviceA"); Enhancer enhancer = new Enhancer(); // 字节码增强 enhancer.setSuperclass(ServiceAImpl.class); // 设置父类 enhancer.setCallback(new MyMethodInterceptor()); // 设置回调方法 IServiceA proxyA = (IServiceA) enhancer.create(); proxyA.sayHello("proxyA"); } } 程序输出: serviceA proxyA