平時工作中很常見的一個場景是對象屬性的復(fù)制,這時我們使用最多的是兩種方式
- 調(diào)用引用包中的BeanUtils.copyProperties方法,調(diào)用很簡單,只需要一行代碼侈咕,還可以設(shè)置
- 自己寫get、set方法逐個設(shè)置
目前常用的工具類是“org.springframework.beans.BeanUtils”或“org.apache.commons.beanutils.BeanUtils”器紧,為知道那個方法效率高耀销,我寫了一個測試類,如下:
import org.junit.Before;
import org.junit.Test;
import org.omg.PortableServer.THREAD_POLICY_ID;
import org.springframework.beans.BeanUtils;
import org.springframework.util.StopWatch;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.concurrent.TimeUnit;
public class TestW {
OrderInfoDto source;
int repeattime = 100000;
@Before
public void before() {
source = new OrderInfoDto();
source.setId(123L);
source.setBundingTime(new Date());
source.setBadJudgeState(14);
source.setBuyerMobile("123456789");
source.setBuyerName("測試");
source.setTs(new Date());
source.setMark(2);
source.setOrderNo(12L);
source.setCreateDate(new Date());
source.setCreateTime(new Date());
source.setBundingTime(new Date());
source.setOrderCombineBeginTime(new Date());
source.setUpdateTime(new Date());
source.setPreFinishTime(new Date());
source.setPickingBeginTime(new Date());
source.setPickingEndTime(new Date());
source.setOrderPreDeliveryTime(new Date());
}
@Test
public void test0() {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
for (int i = 0; i < repeattime ; i++) {
OrderInfoDto target = new OrderInfoDto();
target.setId(source.getId());
target.setBundingTime(source.getBundingTime());
target.setBadJudgeState(source.getBadJudgeState());
target.setBuyerMobile(source.getBuyerMobile());
target.setBuyerName(source.getBuyerName());
target.setTs(source.getTs());
target.setMark(source.getMark());
target.setOrderNo(source.getOrderNo());
target.setCreateDate(source.getCreateDate());
target.setCreateTime(source.getCreateDate());
target.setBundingTime(source.getCreateDate());
target.setOrderCombineBeginTime(source.getCreateDate());
target.setUpdateTime(source.getCreateDate());
target.setPreFinishTime(source.getCreateDate());
target.setPickingBeginTime(source.getCreateDate());
target.setPickingEndTime(source.getCreateDate());
target.setOrderPreDeliveryTime(source.getCreateDate());
}
stopWatch.stop();
System.out.println(stopWatch.getTotalTimeSeconds());
}
@Test
public void testSpring() throws InterruptedException {
// TimeUnit.SECONDS.sleep(3);
StopWatch stopWatch = new StopWatch();
stopWatch.start();
for (int i = 0; i < repeattime ; i++) {
OrderInfoDto target = new OrderInfoDto();
BeanUtils.copyProperties(source,target);
}
stopWatch.stop();
System.out.println(stopWatch.getTotalTimeSeconds());
// TimeUnit.DAYS.sleep(1);
}
@Test
public void testApache() throws InvocationTargetException, IllegalAccessException, InterruptedException {
// TimeUnit.SECONDS.sleep(3);
StopWatch stopWatch = new StopWatch();
stopWatch.start();
for (int i = 0; i < repeattime ; i++) {
OrderInfoDto target = new OrderInfoDto();
org.apache.commons.beanutils.BeanUtils.copyProperties(target,source);
}
stopWatch.stop();
System.out.println(stopWatch.getTotalTimeSeconds());
// TimeUnit.DAYS.sleep(1);
}
}
結(jié)果如下铲汪,其中java方式是使用get/set方式設(shè)置屬性值熊尉。
從結(jié)果來看使用get/set方法是最快的罐柳。spring和Apache都是用了反射機(jī)制實現(xiàn)的屬性復(fù)制。
那為什么反射會比直接使用get/set慢那么多呢狰住!我從java 官方的 javatutorials 找到了一些線索张吉。
Drawbacks of Reflection
Reflection is powerful, but should not be used indiscriminately. If it is possible to perform an operation without using reflection, then it is preferable to avoid using it. The following concerns should be kept in mind when accessing code via reflection.
Performance Overhead
Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.
Security Restrictions
Reflection requires a runtime permission which may not be present when running under a security manager. This is in an important consideration for code which has to run in a restricted security context, such as in an Applet.
Exposure of Internals
Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may destroy portability. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform.
建議: 對性能要求比較高的系統(tǒng)不要偷懶,使用get/set方式催植。
問題:在測試的時候想知道spring或Apache哪個操作花的時間比較多肮蛹,但是一直沒找到比較通用的方法,能得到某個方法的執(zhí)行時間创南。有好心的網(wǎng)友能給出答案不勝感激額伦忠!