JDK动态代理
静态代理其实就是事先写好代理类,可以手工编写也可以使用工具生成,但它的缺点是每个业务类都要对应一个代理类,特别不灵活也不方便,于是就有了动态代理。
动态代理的常见使用场景有 RPC 框架的封装、AOP(面向切面编程)的实现、JDBC 的连接等。
Spring 框架中同时使用了两种动态代理 JDK Proxy 和 CGLib,当 Bean 实现了接口时,Spring 就会使用 JDK Proxy,在没有实现接口时就会使用 CGLib,我们也可以在配置中指定强制使用 CGLib,只需要在 Spring 配置中添加 <aop:aspectj-autoproxy proxy-target-class="true"/> 即可。
创建接口
创建 CarService 接口:
interface CarService {void running();void stop();}
创建接口实现类
创建 CarService 的实现类 BusCarServiceImpl:
class BusCarServiceImpl implements CarService {@Overridepublic void running() {System.out.println("car running");}@Overridepublic void stop() {System.out.println("car stop");}}
创建 JDK InvocationHandler 实现类
创建 JDKProxy 类实现 InvocationHandler 的 invoke 方法:
class JDKProxy<T> implements InvocationHandler {/*** 被代理的对象*/private T target;public JDKProxy(T target) {this.target = target;}/*** 生成代理对象*/public T getProxyInstant() {return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("代理执行,被代理的方法:" + method.getName() + ",被代理的类:" + target.getClass().getSimpleName());return method.invoke(target, args);}}
测试
public static void main(String[] args) {// 获取代理对象JDKProxy<CarService> jdkProxy = new JDKProxy<>(new BusCarServiceImpl());CarService busCarServiceImpl = jdkProxy.getProxyInstant();// 调用代理对象的方法busCarServiceImpl.running();busCarServiceImpl.stop();}
运行结果:
代理执行,被代理的方法:running,被代理的类:BusCarServiceImplcar running代理执行,被代理的方法:stop,被代理的类:BusCarServiceImplcar stop
CGlib动态代理
CGlib 动态代理相比于 JDK 动态代理的好处就是非接口方法也能实现代理。
引入 CGlib 依赖
<!-- https://mvnrepository.com/artifact/cglib/cglib --><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version></dependency>
创建接口
创建接口实现类
创建 CarService 的实现类 BusCarServiceImpl,其中 general 方法是非接口方法,用于体现 CGlib 动态代理与 JDK 动态代理的不同之处:
class BusCarServiceImpl implements CarService {@Overridepublic void running() {System.out.println("car running");}@Overridepublic void stop() {System.out.println("car stop");}public void general() {System.out.println("general");}}
创建 CGlib MethodInterceptor 实现类
创建 CGLibProxy 类实现 MethodInterceptor 的 intercept 方法:
class CGLibProxy<T> implements MethodInterceptor {/*** 被代理的对象*/private T target;public CGLibProxy(T target) {this.target = target;}/*** 生成代理对象*/public T getProxyInstant() {Enhancer enhancer = new Enhancer();// 设置父类为实例类enhancer.setSuperclass(this.target.getClass());// 回调方法enhancer.setCallback(this);// 创建代理对象return (T) enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("代理执行,被代理的方法:" + method.getName() + ",被代理的类:" + target.getClass().getSimpleName());return methodProxy.invokeSuper(o, objects);}}
测试
public static void main(String[] args) {// 获取代理对象CGLibProxy<BusCarServiceImpl> cgLibProxy = new CGLibProxy<>(new BusCarServiceImpl());BusCarServiceImpl carService = cgLibProxy.getProxyInstant();// 调用代理对象的方法carService.running();carService.stop();// 非接口方法也能被代理carService.general();}
运行结果:
代理执行,被代理的方法:running,被代理的类:BusCarServiceImplcar running代理执行,被代理的方法:stop,被代理的类:BusCarServiceImplcar stop代理执行,被代理的方法:general,被代理的类:BusCarServiceImplgeneral
