• java动态代理两种实现方式


    代理顾名思义就是代理别人完成某件任务,比如张三代理李四去交物业费。张三就是代理人,李四就是被代理人。

    Java代理实现,有静态代理和动态代理,静态代理就是代码在编译成class文件后,就已经有代理类的class文件了,但是动态代理需要在运行时动态生成一个代理类的class,比如:

    Class stuProxyClass = Proxy.getProxyClass(Person.class.getClassLoader(), new Class[] {Person.class});
    运行时动态生成一个学生的代理类。

    代理主要用来做代码功能的增强,比如spring里面的aop(比如面向切面做一个controller日志增强,就不用每个controller里面写日志),事务都是通过动态代理来实现的,jdk适用于被代理对象需要实现接口,而cglib无需被代理对象实现了接口。有时候,比如我们使用了第三方的jar里面的某个类,我们想对他做功能增强,但是又不能改代码?咋办?动态代理就可以帮助我们实现了,我们为这个需要增强的类做一个代理。在代理里面拦截方法,继而做功能增强。本文写的两个demo,一个模拟订单服务,一个模拟用户服务。在新增订单时,通过代理类打印订单数据的日志。新增用户时,打印用户信息。

    动态代理有两种实现方式:

    方式一:通过JDK自带的反射实现

    java.lang.reflect.InvocationHandler和java.lang.reflect.Proxy;

    jdk实现的需要有一个接口

    OrderService.java接口:

    1. package com.figo.study2022.service;
    2. import java.util.Map;
    3. /**
    4. * @ClassName:OrderService
    5. * @PackageName:com.figo.study2022.service.impl
    6. * @Description:类描述
    7. * @Date:2022/9/19 20:24
    8. * @Author:figo
    9. */
    10. public interface OrderService {
    11. public void addOrder(Map params);
    12. }
    OrderServiceImpl.java实现类
    1. package com.figo.study2022.service.impl;
    2. import com.figo.study2022.service.OrderService;
    3. import java.util.Map;
    4. /**
    5. * @ClassName:OrderServiceImpl
    6. * @PackageName:com.figo.study2022.service.impl
    7. * @Description:类描述
    8. * @Date:2022/9/19 20:26
    9. * @Author:figo
    10. */
    11. public class OrderServiceImpl implements OrderService {
    12. @Override
    13. public void addOrder(Map params) {
    14. System.out.println("add Order 成功!");
    15. }
    16. }

    OrderServiceProxy.java增强处理类

    1. package com.figo.study2022.service.proxy;
    2. import java.lang.reflect.InvocationHandler;
    3. import java.lang.reflect.Method;
    4. /**
    5. * @ClassName:OrderServiceProxy
    6. * @PackageName:com.figo.study2022.service.proxy
    7. * @Description:类描述
    8. * @Date:2022/9/19 21:11
    9. * @Author:figo
    10. */
    11. public class OrderServiceProxy implements InvocationHandler {
    12. private Object realObj;
    13. public Object getRealObj() {
    14. return realObj;
    15. }
    16. public void setRealObj(Object realObj) {
    17. this.realObj = realObj;
    18. }
    19. public OrderServiceProxy(Object realObj) {
    20. super();
    21. this.realObj = realObj;
    22. }
    23. @Override
    24. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    25. if(args!=null&&args.length>0) {
    26. int size=args.length;
    27. StringBuffer buffer=new StringBuffer();
    28. for(int a=0;a
    29. {
    30. buffer.append(args[a]);
    31. buffer.append(",");
    32. }
    33. System.out.println("代理OrderService对象做日志增强,获取到的参数为=" + buffer.toString());
    34. }
    35. Object ret = method.invoke(realObj,args);
    36. return ret;
    37. }
    38. }

    Test.java测试类

    1. package com.figo.study2022;
    2. import com.figo.study2022.service.OrderService;
    3. import com.figo.study2022.service.impl.OrderServiceImpl;
    4. import com.figo.study2022.service.impl.UserServiceImpl;
    5. import com.figo.study2022.service.proxy.OrderServiceProxy;
    6. import com.figo.study2022.service.proxy.UserServiceProxy;
    7. import org.springframework.cglib.proxy.Enhancer;
    8. import org.springframework.cglib.proxy.MethodInterceptor;
    9. import org.springframework.cglib.proxy.MethodProxy;
    10. import java.lang.reflect.InvocationHandler;
    11. import java.lang.reflect.Method;
    12. import java.lang.reflect.Proxy;
    13. import java.util.HashMap;
    14. import java.util.Map;
    15. /**
    16. * @ClassName:Test
    17. * @PackageName:com.figo.study2022
    18. * @Description:类描述
    19. * @Date:2022/9/19 20:29
    20. * @Author:figo
    21. */
    22. public class Test {
    23. public static void main(String[] args) {
    24. OrderService orderService = new OrderServiceImpl();
    25. Map params=new HashMap();
    26. params.put("orderId","20220919204100001");
    27. params.put("orderTime","20220919204100");
    28. params.put("orderAmt",100);
    29. /**
    30. * 1.通过jdk反射来实现动态代理
    31. * java.lang.reflect.InvocationHandler
    32. */
    33. //写法一:通过匿名对象来代理,这样写免去写代理类
    34. OrderService proxyOrderService = (OrderService) Proxy.newProxyInstance(orderService.getClass().getClassLoader(), orderService.getClass().getInterfaces(), new InvocationHandler() {
    35. @Override
    36. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    37. //args表示有几个参数,这里只有一个参数
    38. System.out.println("代理OrderService做日志增强,收到的请求参数是:"+args[0].toString());
    39. //这里调用真实对象的方法
    40. return method.invoke(orderService, args);
    41. }
    42. });
    43. proxyOrderService.addOrder(params);
    44. //写法二:写个jdk动态代理类来实现
    45. OrderServiceProxy osp = new OrderServiceProxy(orderService);
    46. OrderService proxy = (OrderService) Proxy.newProxyInstance(orderService.getClass().getClassLoader(),orderService.getClass().getInterfaces(),osp);
    47. proxy.addOrder(params);
    48. }
    49. }

    方式二:通过第三方CGLIB来实现

    UserServiceImpl.java实现类,无需继承接口
    1. package com.figo.study2022.service.impl;
    2. /**
    3. * @ClassName:UserServiceImpl
    4. * @PackageName:com.figo.study2022.service.impl
    5. * @Description:使用cgilib实现动态代理,被代理类无需实现接口
    6. * @Date:2022/9/20 9:34
    7. * @Author:figo
    8. */
    9. public class UserServiceImpl {
    10. public void addUser(String name,int age,String sex)
    11. {
    12. System.out.println("添加用户成功!");
    13. }
    14. }

    UserServiceProxy.java方法拦截类
    1. package com.figo.study2022.service.proxy;
    2. import org.springframework.cglib.proxy.MethodInterceptor;
    3. import org.springframework.cglib.proxy.MethodProxy;
    4. import java.lang.reflect.Method;
    5. /**
    6. * @ClassName:UserServiceProxy
    7. * @PackageName:com.figo.study2022.service.proxy
    8. * @Description:类描述
    9. * @Date:2022/9/20 9:35
    10. * @Author:figo
    11. */
    12. public class UserServiceProxy implements MethodInterceptor {
    13. private Object realObj;
    14. public Object getRealObj() {
    15. return realObj;
    16. }
    17. public void setRealObj(Object realObj) {
    18. this.realObj = realObj;
    19. }
    20. public UserServiceProxy(Object realObj) {
    21. super();
    22. this.realObj = realObj;
    23. }
    24. @Override
    25. public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    26. //参数检查
    27. if(objects!=null&&objects.length>0) {
    28. int size=objects.length;
    29. StringBuffer buffer=new StringBuffer();
    30. for(int a=0;a
    31. {
    32. buffer.append(objects[a]);
    33. buffer.append(",");
    34. }
    35. System.out.println("代理UserService对象做日志增强,获取到的参数为=" + buffer.toString());
    36. }
    37. //调用真实对象的方法
    38. Object ret =method.invoke(realObj,objects);
    39. return ret;
    40. }
    41. }

    Test.java测试类

    1. package com.figo.study2022;
    2. import com.figo.study2022.service.OrderService;
    3. import com.figo.study2022.service.impl.OrderServiceImpl;
    4. import com.figo.study2022.service.impl.UserServiceImpl;
    5. import com.figo.study2022.service.proxy.OrderServiceProxy;
    6. import com.figo.study2022.service.proxy.UserServiceProxy;
    7. import org.springframework.cglib.proxy.Enhancer;
    8. import org.springframework.cglib.proxy.MethodInterceptor;
    9. import org.springframework.cglib.proxy.MethodProxy;
    10. import java.lang.reflect.InvocationHandler;
    11. import java.lang.reflect.Method;
    12. import java.lang.reflect.Proxy;
    13. import java.util.HashMap;
    14. import java.util.Map;
    15. /**
    16. * @ClassName:Test
    17. * @PackageName:com.figo.study2022
    18. * @Description:类描述
    19. * @Date:2022/9/19 20:29
    20. * @Author:figo
    21. */
    22. public class Test {
    23. public static void main(String[] args) {
    24. /**
    25. * 2.通过cglib实现动态代理
    26. * 有时候调用第三方jar,不方便改动里面的代码,但是又希望做功能增强
    27. * 可以采用动态代理来实现
    28. */
    29. //方法一:通过匿名对象来实现
    30. UserServiceImpl userServiceImpl = new UserServiceImpl();
    31. //创建enhancer对象
    32. Enhancer enhancer = new Enhancer();
    33. //设置代理的父类
    34. enhancer.setSuperclass(UserServiceImpl.class);
    35. //对方法做拦截
    36. enhancer.setCallback(new MethodInterceptor() {
    37. @Override
    38. public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    39. //参数检查
    40. if(args!=null&&args.length>0) {
    41. int size=args.length;
    42. StringBuffer buffer=new StringBuffer();
    43. for(int a=0;a
    44. {
    45. buffer.append(args[a]);
    46. buffer.append(",");
    47. }
    48. System.out.println("代理UserService对象做日志增强,获取到的参数为=" + buffer.toString());
    49. }
    50. //调用真实对象的方法s
    51. return method.invoke(userServiceImpl, args);
    52. }
    53. });
    54. UserServiceImpl userServiceImplProxy = (UserServiceImpl) enhancer.create();
    55. userServiceImplProxy.addUser("andy",18,"男");
    56. //方法二:通过代理类来实现
    57. Enhancer enhancer1 = new Enhancer();
    58. enhancer1.setSuperclass(UserServiceImpl.class);
    59. enhancer1.setCallback(new UserServiceProxy(new UserServiceImpl()));
    60. UserServiceImpl userServiceImplProxy1 = (UserServiceImpl) enhancer.create();
    61. userServiceImplProxy1.addUser("jane",16,"女");
    62. }
    63. }

  • 相关阅读:
    java毕业设计一点就到家外卖订餐系统Mybatis+系统+数据库+调试部署
    Python条件语句的用法
    PCA推导以及iris实例
    如何使用 Xshell 连接 Linux 服务器
    Linux进阶-编辑器以及Shell编程
    关于#sql#的问题:高斯库中查询一个字段所有值中是否包含某个值,有没有简单的函数,不用切割函数的sql语录比较简单的推荐下
    性能测试学习-基本使用-元件组件介绍(二)
    腾讯云轻量应用服务器详细介绍_轻量值得买吗?
    商品管理模块微服务demo
    spss显著性不高怎么调整数据?
  • 原文地址:https://blog.csdn.net/figo0423/article/details/126949877