JDK代理:

基于接口的动态代理技术
准备目标接口,目标接口实现,增强方法

  1. /**
  2. * @description: 目标接口
  3. * @Author C_Y_J
  4. * @create 2021-03-01 09:37
  5. **/
  6. public interface TargetInterface {
  7. void save();
  8. }
  9. /**
  10. * @description: 目标接口的实现
  11. * @Author C_Y_J
  12. * @create 2021-03-01 09:38
  13. **/
  14. public class TargetInterfaceImpl implements TargetInterface {
  15. @Override
  16. public void save() {
  17. System.out.println("目标接口的实现 run ...");
  18. }
  19. }
  20. /**
  21. * @description: 增强方法
  22. * @Author C_Y_J
  23. * @create 2021-03-01 09:39
  24. **/
  25. public class Advice {
  26. public void before(){
  27. System.out.println("前置增强");
  28. }
  29. public void afterReturning(){
  30. System.out.println("后置增强");
  31. }
  32. }

准备基于jdk动态代理对象

  1. /**
  2. * @description: 动态代理对象测试
  3. * @Author C_Y_J
  4. * @create 2021-03-01 09:42
  5. **/
  6. public class ProxyJdkTest {
  7. public static void main(String[] args) {
  8. TargetInterfaceImpl targetInterface = new TargetInterfaceImpl();
  9. Advice advice = new Advice();
  10. /*
  11. * 在这里需要三个参数
  12. * Proxy.newProxyInstance 返回就是产生的动态代理对象,返回值必须要用TargetInterface 接口接收
  13. * */
  14. TargetInterface proxyInstance = (TargetInterface) Proxy.newProxyInstance(
  15. //(1)目标对象 类加载器
  16. targetInterface.getClass().getClassLoader(),
  17. //(2)目标对象 相同接口 字节码数组
  18. targetInterface.getClass().getInterfaces(),
  19. new InvocationHandler() {
  20. /*
  21. *(3)
  22. * 调用动态代理对象的任何方法,实际上调用的是底下的invoke方法
  23. * proxy:代理对象
  24. * method:目标方法对象
  25. * */
  26. @Override
  27. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  28. //(5)前置增强
  29. advice.before();
  30. //(4)有人看到这里目标方法调用了invoke方法,会认为是回调!!!
  31. // 上面的invoke是动态代理对象的invoke,下面的invoke是反射
  32. method.invoke(targetInterface, args);
  33. //(6)后置增强
  34. advice.afterReturning();
  35. return null;
  36. }
  37. }
  38. );
  39. //测试
  40. proxyInstance.save();
  41. }
  42. }
  1. Proxy.newProxyInstance() 需要三个参数:(1)目标对象 类加载器、(2)目标对象 相同接口 字节码数组、(3new InvocationHandler()。
  2. Proxy.newProxyInstance() 返回就是产生的动态代理对象,返回值必须要用接口接收,因为要保证动态代理对象和目标接口实现是属于兄弟关系

cglib代理:

导入相关依赖:

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework</groupId>
  4. <artifactId>spring-context</artifactId>
  5. <version>5.0.5.RELEASE</version>
  6. </dependency>
  7. </dependencies>


在spring-context下有spring-core依赖,查看发现已经加入了cglib的源码**
Jdk和Cglib的动态代理对象 - 图1

准备目标方法,增强方法。代码和上面一样,我不重复写
准备基于cglib动态代理对象

  1. /**
  2. * @description: 动态代理对象测试
  3. * @Author C_Y_J
  4. * @create 2021-03-01 09:42
  5. **/
  6. public class ProxyCglibTest {
  7. public static void main(String[] args) {
  8. TargetInterfaceImpl targetInterface = new TargetInterfaceImpl();
  9. Advice advice = new Advice();
  10. //1、创建增强器
  11. Enhancer enhancer = new Enhancer();
  12. //2、设置父类(其实就是目标类)
  13. enhancer.setSuperclass(TargetInterfaceImpl.class);
  14. //3、设置回调 setCallback() 需要的参数是Callback接口,我们用Callback接口下的MethodInterceptor子接口
  15. enhancer.setCallback(new MethodInterceptor() {
  16. @Override
  17. public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
  18. //前置方法
  19. advice.before();
  20. //目标方法
  21. method.invoke(targetInterface, args);
  22. //后置方法
  23. advice.afterReturning();
  24. return null;
  25. }
  26. });
  27. //4、创建代理对象,返回值可以用TargetInterfaceImpl 子类接收
  28. TargetInterfaceImpl proxy = (TargetInterfaceImpl) enhancer.create();
  29. //测试
  30. proxy.save();
  31. }
  32. }
  1. enhancer.setSuperclass(TargetInterfaceImpl.class) 设置父类(其实就是目标类)
  2. enhancer.setCallback() 设置回调 setCallback() 需要的参数是Callback接口,我们用Callback接口下的MethodInterceptor子接口
  3. enhancer.create() 返回值可以用TargetInterfaceImpl 子类接收,因为动态代理对象和目标对象是属于父子关系