zoukankan      html  css  js  c++  java
  • Beanutils.copyProperties( )的使用与优化

    1.使用原因

       因为现在都是前后端分离所以我们在响应APP端或者前端的时候会维护一套VO,那么DTO到VO的转换便是一堆get... set...这样的代码,比如好几个地方用到的话还要去复制粘贴来转换。所以这里的我就开始动脑子了。

    2.解决问题

     刚开始项目中是好几个地方在用,然后我就想把这段VO转换的代码抽取出来,先是想写个工具类,后来一想这是业务的代码。然后就写了一个抽象类。正好让其他接口直接继承。完美解决。

    然后是发现VO转换的地方很多,有没有更方便的转换方法? 要不然一堆代码岂不是很掉价

    3.使用Beanutils

    这里使用的是 org.springframework.beans包下的copyProperties( )方法,他会把字段相同的Bean字段赋值,大大减少了代码量,但从其他程序员的建议说,这个操作会响应性能,数据量大的时候还没有直接get ,set性能好。

    4.优化

    这里是参考了这个大神的博客,ReflectASM,高性能的反射。 使用的话需要引入下面的依赖。

    <!-- https://mvnrepository.com/artifact/com.esotericsoftware.reflectasm/reflectasm -->
    <dependency>
    <groupId>com.esotericsoftware.reflectasm</groupId>
    <artifactId>reflectasm</artifactId>
    <version>1.05</version>
    </dependency>

    ReflectASM是一个很小的java类库,主要是通过asm生产类来实现java反射,执行速度非常快。
    大家如果想优化的话,可以试试下面的方法。


    1. public static void main(String[] args) {    
    2.         User user = new User();    
    3.         //使用reflectasm生产User访问类    
    4.         MethodAccess access = MethodAccess.get(User.class);    
    5.         //invoke setName方法name值    
    6.         access.invoke(user, "setName", "张三");    
    7.         //invoke getName方法 获得值    
    8.         String name = (String)access.invoke(user, "getName", null);    
    9.         System.out.println(name);    
    10.     }    
    原理 
       上面代码的确实现反射的功能,代码主要的核心是 MethodAccess.get(User.class); 
    看了下源码,这段代码主要是通过asm生产一个User的处理类 UserMethodAccess(这个类主要是实现了invoke方法)的ByteCode,然后获得该对象,通过上面的invoke操作user类。 

    ASM反射转换:

    [java] view plain copy
     
     
     
     
      1. private static Map<Class, MethodAccess> methodMap = new HashMap<Class, MethodAccess>();  
      2.   
      3.     private static Map<String, Integer> methodIndexMap = new HashMap<String, Integer>();  
      4.   
      5.     private static Map<Class, List<String>> fieldMap = new HashMap<Class, List<String>>();  
      6.   
      7.     public static void copyProperties(Object desc, Object orgi) {  
      8.         MethodAccess descMethodAccess = methodMap.get(desc.getClass());  
      9.         if (descMethodAccess == null) {  
      10.             descMethodAccess = cache(desc);  
      11.         }  
      12.         MethodAccess orgiMethodAccess = methodMap.get(orgi.getClass());  
      13.         if (orgiMethodAccess == null) {  
      14.             orgiMethodAccess = cache(orgi);  
      15.         }  
      16.   
      17.         List<String> fieldList = fieldMap.get(orgi.getClass());  
      18.         for (String field : fieldList) {  
      19.             String getKey = orgi.getClass().getName() + "." + "get" + field;  
      20.             String setkey = desc.getClass().getName() + "." + "set" + field;  
      21.             Integer setIndex = methodIndexMap.get(setkey);  
      22.             if (setIndex != null) {  
      23.                 int getIndex = methodIndexMap.get(getKey);  
      24.                 // 参数一需要反射的对象  
      25.                 // 参数二class.getDeclaredMethods 对应方法的index  
      26.                 // 参数对三象集合  
      27.                 descMethodAccess.invoke(desc, setIndex.intValue(),  
      28.                         orgiMethodAccess.invoke(orgi, getIndex));  
      29.             }  
      30.         }  
      31.     }  
      32.   
      33.     // 单例模式  
      34.     private static MethodAccess cache(Object orgi) {  
      35.         synchronized (orgi.getClass()) {  
      36.             MethodAccess methodAccess = MethodAccess.get(orgi.getClass());  
      37.             Field[] fields = orgi.getClass().getDeclaredFields();  
      38.             List<String> fieldList = new ArrayList<String>(fields.length);  
      39.             for (Field field : fields) {  
      40.                 if (Modifier.isPrivate(field.getModifiers())  
      41.                         && !Modifier.isStatic(field.getModifiers())) { // 是否是私有的,是否是静态的  
      42.                     // 非公共私有变量  
      43.                     String fieldName = StringUtils.capitalize(field.getName()); // 获取属性名称  
      44.                     int getIndex = methodAccess.getIndex("get" + fieldName); // 获取get方法的下标  
      45.                     int setIndex = methodAccess.getIndex("set" + fieldName); // 获取set方法的下标  
      46.                     methodIndexMap.put(orgi.getClass().getName() + "." + "get"  
      47.                             + fieldName, getIndex); // 将类名get方法名,方法下标注册到map中  
      48.                     methodIndexMap.put(orgi.getClass().getName() + "." + "set"  
      49.                             + fieldName, setIndex); // 将类名set方法名,方法下标注册到map中  
      50.                     fieldList.add(fieldName); // 将属性名称放入集合里  
      51.                 }  
      52.             }  
      53.             fieldMap.put(orgi.getClass(), fieldList); // 将类名,属性名称注册到map中  
      54.             methodMap.put(orgi.getClass(), methodAccess);  
      55.             return methodAccess;  
      56.         }  
      57.     }  

    参考---https://blog.csdn.net/w05980598/article/details/79134379

  • 相关阅读:
    spring注解之@Lazy
    HttpClient之EntityUtils对象
    HTTP协议(Requset、Response)
    SpringBoot SpringSession redis SESSION
    Spring-session redis 子域名 session
    Spring Boot Servlet
    版本管理
    Spring AOP @Aspect
    Spring 事务配置的五种方式
    Spring <tx:annotation-driven>注解 JDK动态代理和CGLIB动态代理 区别。
  • 原文地址:https://www.cnblogs.com/technologykai/p/9323166.html
Copyright © 2011-2022 走看看