JDK动态代理

静态代理其实就是事先写好代理类,可以手工编写也可以使用工具生成,但它的缺点是每个业务类都要对应一个代理类,特别不灵活也不方便,于是就有了动态代理。
动态代理的常见使用场景有 RPC 框架的封装、AOP(面向切面编程)的实现、JDBC 的连接等。
Spring 框架中同时使用了两种动态代理 JDK Proxy 和 CGLib,当 Bean 实现了接口时,Spring 就会使用 JDK Proxy,在没有实现接口时就会使用 CGLib,我们也可以在配置中指定强制使用 CGLib,只需要在 Spring 配置中添加 <aop:aspectj-autoproxy proxy-target-class="true"/> 即可。

创建接口

创建 CarService 接口:

  1. interface CarService {
  2. void running();
  3. void stop();
  4. }

创建接口实现类

创建 CarService 的实现类 BusCarServiceImpl

  1. class BusCarServiceImpl implements CarService {
  2. @Override
  3. public void running() {
  4. System.out.println("car running");
  5. }
  6. @Override
  7. public void stop() {
  8. System.out.println("car stop");
  9. }
  10. }

创建 JDK InvocationHandler 实现类

创建 JDKProxy 类实现 InvocationHandlerinvoke 方法:

  1. class JDKProxy<T> implements InvocationHandler {
  2. /**
  3. * 被代理的对象
  4. */
  5. private T target;
  6. public JDKProxy(T target) {
  7. this.target = target;
  8. }
  9. /**
  10. * 生成代理对象
  11. */
  12. public T getProxyInstant() {
  13. return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
  14. }
  15. @Override
  16. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  17. System.out.println("代理执行,被代理的方法:" + method.getName() + ",被代理的类:" + target.getClass().getSimpleName());
  18. return method.invoke(target, args);
  19. }
  20. }

测试

  1. public static void main(String[] args) {
  2. // 获取代理对象
  3. JDKProxy<CarService> jdkProxy = new JDKProxy<>(new BusCarServiceImpl());
  4. CarService busCarServiceImpl = jdkProxy.getProxyInstant();
  5. // 调用代理对象的方法
  6. busCarServiceImpl.running();
  7. busCarServiceImpl.stop();
  8. }

运行结果:

  1. 代理执行,被代理的方法:running,被代理的类:BusCarServiceImpl
  2. car running
  3. 代理执行,被代理的方法:stop,被代理的类:BusCarServiceImpl
  4. car stop

CGlib动态代理

CGlib 动态代理相比于 JDK 动态代理的好处就是非接口方法也能实现代理。

引入 CGlib 依赖

  1. <!-- https://mvnrepository.com/artifact/cglib/cglib -->
  2. <dependency>
  3. <groupId>cglib</groupId>
  4. <artifactId>cglib</artifactId>
  5. <version>3.3.0</version>
  6. </dependency>

创建接口

省略,与 JDK 动态代理一样。

创建接口实现类

创建 CarService 的实现类 BusCarServiceImpl,其中 general 方法是非接口方法,用于体现 CGlib 动态代理与 JDK 动态代理的不同之处:

  1. class BusCarServiceImpl implements CarService {
  2. @Override
  3. public void running() {
  4. System.out.println("car running");
  5. }
  6. @Override
  7. public void stop() {
  8. System.out.println("car stop");
  9. }
  10. public void general() {
  11. System.out.println("general");
  12. }
  13. }

创建 CGlib MethodInterceptor 实现类

创建 CGLibProxy 类实现 MethodInterceptorintercept 方法:

  1. class CGLibProxy<T> implements MethodInterceptor {
  2. /**
  3. * 被代理的对象
  4. */
  5. private T target;
  6. public CGLibProxy(T target) {
  7. this.target = target;
  8. }
  9. /**
  10. * 生成代理对象
  11. */
  12. public T getProxyInstant() {
  13. Enhancer enhancer = new Enhancer();
  14. // 设置父类为实例类
  15. enhancer.setSuperclass(this.target.getClass());
  16. // 回调方法
  17. enhancer.setCallback(this);
  18. // 创建代理对象
  19. return (T) enhancer.create();
  20. }
  21. @Override
  22. public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
  23. System.out.println("代理执行,被代理的方法:" + method.getName() + ",被代理的类:" + target.getClass().getSimpleName());
  24. return methodProxy.invokeSuper(o, objects);
  25. }
  26. }

测试

  1. public static void main(String[] args) {
  2. // 获取代理对象
  3. CGLibProxy<BusCarServiceImpl> cgLibProxy = new CGLibProxy<>(new BusCarServiceImpl());
  4. BusCarServiceImpl carService = cgLibProxy.getProxyInstant();
  5. // 调用代理对象的方法
  6. carService.running();
  7. carService.stop();
  8. // 非接口方法也能被代理
  9. carService.general();
  10. }

运行结果:

  1. 代理执行,被代理的方法:running,被代理的类:BusCarServiceImpl
  2. car running
  3. 代理执行,被代理的方法:stop,被代理的类:BusCarServiceImpl
  4. car stop
  5. 代理执行,被代理的方法:general,被代理的类:BusCarServiceImpl
  6. general