当前位置:网站首页>Why is it not recommended to use BeanUtils in production?
Why is it not recommended to use BeanUtils in production?
2022-07-03 01:28:00 【Morning Xi light】
The main reason for not recommending is :
Some attribute copying tools have poor performance
Some attribute copying tools have “BUG” send
There are some hidden dangers when using attribute copying tools ( Later examples will talk about )
Example
First of all, the company has encountered commons Bag BeanUtils A real case of poor property copy performance , Then the colleague changed to Spring Of BeanUtils The performance is much better , If you are interested, you can use the performance test framework or benchmark framework to compare , There is no comparison here .
Now let's see Spring Of BeanUtils What are the problems with copying the properties of :
import lombok.Data;
import java.util.List;
@Data
public class A {
private String name;
private List<Integer> ids;
}
@Data
public class B {
private String name;
private List<String> ids;
}
import org.springframework.beans.BeanUtils;
import java.util.Arrays;
public class BeanUtilDemo {
public static void main(String[] args) {
A first = new A();
first.setName("demo");
first.setIds(Arrays.asList(1, 2, 3));
B second = new B();
BeanUtils.copyProperties(first, second);
for (String each : second.getIds()) {// Type conversion exception
System.out.println(each);
}
}
}
When you run the above example , A type conversion exception occurs .
At the break point, you can see , After the attribute is copied B Type of second In the object ids Still for Integer type :

If not converted to a string , Print directly , No errors are reported .
Use CGlib Not defined in Converter Similar problems will be encountered in the case of :
import org.easymock.cglib.beans.BeanCopier;
import java.util.Arrays;
public class BeanUtilDemo {
public static void main(String[] args) {
A first = new A();
first.setName("demo");
first.setIds(Arrays.asList(1, 2, 3));
B second = new B();
final BeanCopier beanCopier = BeanCopier.create(A.class, B.class, false);
beanCopier.copy(first,second,null);
for (String each : second.getIds()) {// Type conversion exception
System.out.println(each);
}
}
}
Again , The problem is exposed at runtime .
Let's take a look mapstruct:
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface Converter {
Converter INSTANCE = Mappers.getMapper(Converter.class);
B aToB(A car);
}
import java.util.Arrays;
public class BeanUtilDemo {
public static void main(String[] args) {
A first = new A();
first.setName("demo");
first.setIds(Arrays.asList(1, 2, 3));
B second = Converter.INSTANCE.aToB(first);
for (String each : second.getIds()) {// normal
System.out.println(each);
}
}
}
Can succeed in A in List<Integer> To B Medium List<String> type .
Let's look at the compiled Converter Implementation class :
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Generated;
import org.springframework.stereotype.Component;
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
comments = "version: 1.3.1.Final, compiler: javac, environment: Java 1.8.0_202 (Oracle Corporation)"
)
@Component
public class ConverterImpl implements Converter {
@Override
public B aToB(A car) {
if ( car == null ) {
return null;
}
B b = new B();
b.setName( car.getName() );
b.setIds( integerListToStringList( car.getIds() ) );
return b;
}
protected List<String> integerListToStringList(List<Integer> list) {
if ( list == null ) {
return null;
}
List<String> list1 = new ArrayList<String>( list.size() );
for ( Integer integer : list ) {
list1.add( String.valueOf( integer ) );
}
return list1;
}
}
Automatically helped us with the conversion , We may not realize that the types are inconsistent .
If we were A Add one to the class String number attribute , stay B Add one to the class Long number attribute , Use mapstruect When number When it is set to non numeric type, it will report .NumberFormatException.
@Override
public B aToB(A car) {
if ( car == null ) {
return null;
}
B b = new B();
b.setName( car.getName() );
if ( car.getNumber() != null ) { // Here's the problem
b.setNumber( Long.parseLong( car.getNumber() ) );
}
b.setIds( integerListToStringList( car.getIds() ) );
return b;
}
Use cglib By default, there is no mapping number attribute ,B Medium number by null.
If you define the converter manually , Use IDEA plug-in unit ( Such as generateO2O) Automatic conversion :
public final class A2BConverter {
public static B from(A first) {
B b = new B();
b.setName(first.getName());
b.setIds(first.getIds());
return b;
}
}
This problem can be found very clearly in the coding phase :

Conclusion
because Java Generics are actually compile time checks , Post compilation generic erasure , Causes the runtime to List<Integer> and List<String> All are List type , It can be assigned normally . This leads to when using many attribute mapping tools , It is not easy to make obvious errors at compile time .
mapstruct Custom annotation processor , The generic types on both sides of the map can be read at compile time , Then map . But this mapping is also terrible , Sometimes we define the wrong type due to carelessness and other reasons , Automatically helped us with the conversion , It will bring a lot of side effects .
The performance of various attribute mapping tools has been briefly compared before , give the result as follows :

Therefore, use attribute conversion tools with caution , If possible, it is recommended to customize the conversion class , Use IDEA Plug in auto fill , Very efficient , A or B Any property type in does not match , Even delete an attribute , Errors can be reported at the compilation stage , And directly call get set The efficiency is also very high , I hope I can help you !
边栏推荐
- C#应用程序界面开发基础——窗体控制(4)——选择类控件
- Mathematical knowledge: step Nim game game game theory
- 【QT】自定义控件的封装
- MySQL foundation 04 MySQL architecture
- 数学知识:台阶-Nim游戏—博弈论
- [FPGA tutorial case 6] design and implementation of dual port RAM based on vivado core
- MySQL --- 数据库查询 - 条件查询
- C application interface development foundation - form control (4) - selection control
- 一位苦逼程序员的找工作经历
- tp6快速安装使用MongoDB实现增删改查
猜你喜欢

Dotconnect for PostgreSQL data provider

MySQL --- 数据库查询 - 基本查询

Excel if formula determines whether the two columns are the same

Why can't the start method be called repeatedly? But the run method can?

Expérience de recherche d'emploi d'un programmeur difficile

leetcode刷题_两数之和 II - 输入有序数组

MySQL foundation 05 DML language

leetcode 6103 — 从树中删除边的最小分数

一比特苦逼程序員的找工作經曆

Androd gradle's substitution of its use module dependency
随机推荐
Using tensorboard to visualize the model, data and training process
Telephone network problems
[C language] detailed explanation of pointer and array written test questions
Androd gradle's substitution of its use module dependency
信息熵的基础
音程的知识的总结
[androd] module dependency replacement of gradle's usage skills
Mathematical Knowledge: Steps - Nim Games - Game Theory
After reading this article, I will teach you to play with the penetration test target vulnhub - drivetingblues-9
如今少年已归来,人间烟火气最抚凡人心 复工了~
[flutter] icons component (fluttericon Download Icon | customize SVG icon to generate TTF font file | use the downloaded TTF icon file)
tp6快速安装使用MongoDB实现增删改查
Vim 9.0正式发布!新版脚本执行速度最高提升100倍
MySQL foundation 06 DDL
Swiftui component Encyclopedia: using scenekit and swiftui to build interactive 3D pie charts (tutorial with source code)
C application interface development foundation - form control (4) - selection control
[my advanced journey of OpenGL learning] collation of Euler angle, rotation order, rotation matrix, quaternion and other knowledge
Test shift right: Elk practice of online quality monitoring
Excel removes the data after the decimal point and rounds the number
[自我管理]时间、精力与习惯管理