动态代理是一种代理机制,通过代理可以让调用者与实现者之间进行 解耦 ,比如进行RPC调用的时候,框架底层的寻址、序列化等。
public class MyDynamicProxy { public static void main (String[] args) { HelloImpl hello = new HelloImpl(); MyInvocationHandler handler = new MyInvocationHandler(hello); // 构造代码实例 Hello proxyHello = (Hello) Proxy.newProxyInstance(HelloImpl.class.getClassLoader(), HelloImpl.class.getInterfaces(), handler); // 调用代理方法 proxyHello.sayHello(); } } interface Hello { void sayHello(); } class HelloImpl implements Hello { @Override public void sayHello() { System.out.println("Hello World"); } } class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Invoking sayHello"); Object result = method.invoke(target, args); return result; } }
需要被调用方实现interface。如果被调用方没有实现interface,则可以用cglib来实现。
package com.lanhuigu.spring.proxy.cglib; public class HelloService { public HelloService() { System.out.println("HelloService构造"); } /** * 该方法不能被子类覆盖,Cglib是无法代理final修饰的方法的 */ final public String sayOthers(String name) { System.out.println("HelloService:sayOthers>>"+name); return null; } public void sayHello() { System.out.println("HelloService:sayHello"); } }
package com.lanhuigu.spring.proxy.cglib; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * 自定义MethodInterceptor */ public class MyMethodInterceptor implements MethodInterceptor{ /** * sub:cglib生成的代理对象 * method:被代理对象方法 * objects:方法入参 * methodProxy: 代理方法 */ @Override public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("======插入前置通知======"); Object object = methodProxy.invokeSuper(sub, objects); System.out.println("======插入后者通知======"); return object; } }
package com.lanhuigu.spring.proxy.cglib; import net.sf.cglib.core.DebuggingClassWriter; import net.sf.cglib.proxy.Enhancer; public class Client { public static void main(String[] args) { // 代理类class文件存入本地磁盘方便我们反编译查看源码 System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D://code"); // 通过CGLIB动态代理获取代理对象的过程 Enhancer enhancer = new Enhancer(); // 设置enhancer对象的父类 enhancer.setSuperclass(HelloService.class); // 设置enhancer的回调对象 enhancer.setCallback(new MyMethodInterceptor()); // 创建代理对象 HelloService proxy= (HelloService)enhancer.create(); // 通过代理对象调用目标方法 proxy.sayHello(); } }
动态代理完美符合Spring AOP等切面编程,简单来说AOP可以看做是对OOP的一个补充,因为OOP对于跨越不同对象或类的分散、纠缠逻辑表现力不够,比如在不同模块的特定阶段做一些事情,类似日志、用户鉴权、全局性异常处理、性能监控、甚至事务处理等: