Система компании всегда использовала компоненты для выполнения операций копирования bean-компонентов.Я просто знаю, что эта операция влияет на производительность, но я понятия не имею, насколько сильно это повлияет. Теперь протестируйте копию Bean, чтобы получить количественные результаты.
Текущие основные компоненты Bean Copy:
-
Apache BeanUtils
-
Spring BeanUtils
-
Cglib BeanCopier
Хорошо известно, что Apache BeanUtils имеет низкую производительность и обычно не рекомендуется. Здесь он не тестируется, тестируются только два последних компонента.
тестовая среда:
- JAVA8
- Spring Boot 2.1.4.RELEASE
- локальный обычный рабочий стол
Тестовый код:
Тестовая функция: Циркулирующие N раз, скопируйте свойства в объекте Telappmodel в Telappdto, время, проведенное для каждого компонента, тем сильнее выполнение времени.
Тестовый класс POJOИсходный класс TelAppModel.java и целевой класс TelAppDto.java являются простыми классами pojo с одинаковыми переменными-членами.
Обычные методы Java set/get реализуют Bean Copy, код показан ниже:
public static void copySetGet(TelAppModel source, TelAppDto target){
target.setId(source.getId());
target.setTelPowerSavingMode((byte)0);
target.setTelSecret(source.getTelSecret());
target.setTelAppId(source.getTelAppId());
target.setTelName(source.getTelName());
target.setDesc(source.getDesc());
}
Spring BeanUtils реализует копирование компонентовкод показывает, как показано ниже:
public static void copyPropertiesSpring(Object source, Object target){
BeanUtils.copyProperties(source, target);
}
Cglib BeanCopier реализует Bean Copyкод показывает, как показано ниже:
public static void copyPropertiesCglib(Object source, Object target){
BeanCopier beanCopier = BeanCopier.create(source.getClass(), target.getClass(), false);
beanCopier.copy(source, target, null);
}
тестовый код: longCount: определяет, сколько раз выполняется копия.
// Инициализировать longCount TelAppModels в качестве тестовых материалов перед выполнением копирования Bean
for(int i = 0; i < longCount; i++){
appModelSourceList.add(createModel());
}
Три метода копирования Bean вызывают этот метод test() по очереди:
// set/get方法
test((a,b) -> copySetGet(a, b));
// spring BeanUtils
test((a,b) -> copyPropertiesSpring(a, b));
// spring BeanCopier
test((a,b) -> copyPropertiesCglib(a, b));
// Этот метод копирует объект TelAppModel в списке в объект TelAppDto поочередно, и печатает время выполнения longCount раз.Для обеспечения точности результата вышеуказанная операция выполняется 3 раза, то есть 3*longCount раз
private void test(BiConsumer<TelAppModel, TelAppDto> biConsumer){
int runNum = 3;
for(int k = 0; k < runNum; k++) {
long loopCount = longCount;
long begin = System.currentTimeMillis();
for (int i = 0; i < loopCount; i++) {
TelAppModel telAppModel1 = appModelSourceList.get(i);
TelAppDto telAppDto = new TelAppDto();
biConsumer.accept(telAppModel1, telAppDto);
}
System.out.println((System.currentTimeMillis() - begin));
}
}
отчет о тестировании:
Запустите 1000,10000,100000,1000000 раз (мс) time: Детали времени следующим образом:
- ○ методы set/get теоретически должны быть самыми быстрыми
- ○ Производительность следующая: метод set/get > Cglib BeanCopier > Sprign BeanUtils
- ○ Spring BeanUtils каждый раз занимает много времени для первого цикла, и он не имеет такого же объема данных, как во второй раз, и данные ненормальны.
При выполнении команды просмотрите время потребляемого времени процессора через JVISULVM, Подробно, следующим образом:
- Когда Spring BeanUtils выполняет метод CachedIntrospectionResults.forClass() в первый раз, он загружает информацию о классе с диска в кеш памяти, а затем последующие операции получают информацию о классе из кеша. Это также объясняет, почему Spring BeanUtils работает медленно. Кроме того, эта операция является синхронной, если несколько потоков загружают один и тот же класс одновременно, возникает ситуация блокировки.
- Весна CopyProperties BeanUtils также занимает много ресурсов ЦП, а это означает, что для фактического выполнения операции копирования Bean потребуется больше времени.
- Глядя на приведенный выше рисунок, видно, что основное время BeanCopier тратит на вызов метода create(). На фактическое выполнение копирующего Бина уходит меньше времени. Теперь мы оптимизируем в соответствии с этим. каждый раз создавая новый BeanCopier, используйте Cache BeanCopier, созданный BeanCopier.create().Измененный код выглядит следующим образом:
static BeanCopier beanCopierStatic = BeanCopier.create(TelAppModel.class, TelAppDto.class, false);
public static void copyPropertiesCglibStatic(Object source, Object target){
beanCopierStatic.copy(source, target, null);
}
Затем выполните 1000, 10000, 100000, 1000000 раз соответственно (миллисекунды): подробное время выглядит следующим образом:
анализировать: Cglib BeanCopier优化,性能大大提高。cglib在性能和set/get方法相差不大
в заключении:
spring beanUtils 和 cglib 性能都还可以接受,如果对性能没有非常苛刻的要求,使用cglib或spring bean utils 问题都问题不大,推荐优先使用cglib