java cglib 性能性能怎么样

当前访客身份:游客 [
当前位置:
发布于 日 0时,
业务分层的时候通过除了Entity类之外还会有一个Dto或者Vo类,在相互传值的时候我们就需要进行一系列繁琐的setter/getter调用。而且当实体特别大的时候会导致代码繁琐,特别难读。不好维护。所以我们需要自动化JavaBean对象属性拷贝这一过程。现提供三种解决方案及其性能对比:1、原生Java反射机制,原汁原味。2、Cglib的BeanMap3、Cglib的BeanCopier当然还有一些,比如commos&BeanUtils&,PropertyUtils.或者Spring的BeanUtils.代码如下。循环100*100*1000次的情况下:方案1:输出6135id:111方案2输出:12328id:111方案三输出:5444id:111从这里可以看出,其实反射性能也不是太差。性能排序为如下BeanMap&反射&BeanCopier反射比BeanMap快2倍,而BeanCopier比反射也没快太多。不能这个测试也是有缺陷的:1、没有对复杂数据类型进行测试。感兴趣的朋友可以进行测试。2、没有缓存BeanCopier对象。这样的话估计方案三会再快点。不过最后代码提供了改良方案
代码片段(5)
1.&[代码]这是通过反射的形式&&&&
public static &T, E& void transalte(T t, E e) {
Method[] tms = t.getClass().getDeclaredMethods();
Method[] tes = e.getClass().getDeclaredMethods();
for (Method m1 : tms) {
if(m1.getName().startsWith("get")||m1.getName().startsWith("is")) {
String mNameSubfix="";
if(m1.getName().startsWith("get")){
mNameSubfix = m1.getName().substring(3);
mNameSubfix = m1.getName().substring(2);
String forName = "set" + mNameS
for (Method m2 : tes) {
if (m2.getName().equals(forName)) {
// 如果参数类型一致,或者m1的返回类型是m2的参数类型的父类或接口
boolean canContinue = m1.getReturnType().isAssignableFrom(m2.getParameterTypes()[0]);
if (canContinue) {
m2.invoke(e, m1.invoke(t));
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e1) {
// TODO Auto-generated catch block
log.debug("DTO 2 Entity转换失败");
e1.printStackTrace();
log.debug("转换完成");
2.&[代码]这是通过Cglib的BeanMap的形式&&&&
GlobalConfig a=new GlobalConfig();
GlobalConfig b=new GlobalConfig();
a.setId("111");
a.setIsFirst(0);
BeanMap map1=BeanMap.create(a);
BeanMap map2=BeanMap.create(b);
for(Object key:map1.keySet()){
if(map2.containsKey(key)){
map2.put(key, map1.get(key));
3.&[代码]这是Cglib的BeanCopier形式&&&&
GlobalConfig a=new GlobalConfig();
GlobalConfig b=new GlobalConfig();
a.setId("111");
a.setIsFirst(0);
BeanCopier bc=BeanCopier.create(GlobalConfig.class, GlobalConfig.class, false);
bc.copy(a, b, null);
4.&[代码]完整代码&&&&
public class Dto2Entity {
private static final Logger log = LoggerFactory.getLogger(Dto2Entity.class);
* DTO对象转换为实体对象。如命名不规范或其他原因导致失败返回null
* @param t
进行转换的对象
* @param e
进行转换的对象
* @return 实体对象
public static &T, E& void transalte(T t, E e) {
Method[] tms = t.getClass().getDeclaredMethods();
Method[] tes = e.getClass().getDeclaredMethods();
for (Method m1 : tms) {
if (m1.getName().startsWith("get")||m1.getName().startsWith("is")) {
String mNameSubfix="";
if(m1.getName().startsWith("get")){
mNameSubfix = m1.getName().substring(3);
mNameSubfix = m1.getName().substring(2);
String forName = "set" + mNameS
for (Method m2 : tes) {
if (m2.getName().equals(forName)) {
// 如果参数类型一致,或者m1的返回类型是m2的参数类型的父类或接口
boolean canContinue = m1.getReturnType().isAssignableFrom(m2.getParameterTypes()[0]);
if (canContinue) {
m2.invoke(e, m1.invoke(t));
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e1) {
// TODO Auto-generated catch block
log.debug("DTO 2 Entity转换失败");
e1.printStackTrace();
log.debug("转换完成");
public static void main(String[] args) {
GlobalConfig a=new GlobalConfig();
GlobalConfig b=new GlobalConfig();
a.setId("111");
a.setIsFirst(0);
long start=System.currentTimeMillis();
for(int i=0;i&;i++){
transalte(a, b);
BeanMap map1=BeanMap.create(a);
BeanMap map2=BeanMap.create(b);
for(Object key:map1.keySet()){
if(map2.containsKey(key)){
map2.put(key, map1.get(key));
BeanCopier bc=BeanCopier.create(GlobalConfig.class, GlobalConfig.class, false);
bc.copy(a, b, null);
long end=System.currentTimeMillis();
System.out.println(end-start);
System.out.println("id:"+b.getId());
5.&[代码]方案三改良形式&&&&
public class MyBeanUtil {
// 使用多线程安全的Map来缓存BeanCopier,由于读操作远大于写,所以性能影响可以忽略
private static ConcurrentHashMap&String, BeanCopier& beanCopierMap = new ConcurrentHashMap&String, BeanCopier&();
private static final Object lock=new Object() ;
public static void copyProperties(Object source, Object target) {
String beanKey = generateKey(source.getClass(), target.getClass());
BeanCopier copier = beanCopierMap.get(beanKey);
if(copier==null){
synchronized(lock){
copier = beanCopierMap.get(beanKey);
if(copier==null){
copier = BeanCopier.create(source.getClass(), target.getClass(), false);
beanCopierMap.putIfAbsent(beanKey, copier);// putIfAbsent已经实现原子操作了。
copier.copy(source, target, null);
private static String generateKey(Class&?& class1, Class&?& class2) {
return class1.toString() + class2.toString();
开源中国-程序员在线工具:
相关的代码(5)
10回/2747阅
有缺陷,没有判断boolean类型的访问器
2楼:小小懒羊羊 发表于
引用来自“Andy市民”的评论有缺陷,没有判断boolean类型的访问器谢谢提醒!
开源从代码分享开始
小小懒羊羊的其它代码不小心走入了cglib的误区
这2天在学习CGLIB,一时兴起用CGLIB实现了一个管理hibernate事务的类,用来在业务层处理事务。首先来看一下代理类,代码如下package com.import java.lang.reflect.Mimport mons.logging.Limport mons.logging.LogFimport org.hibernate.HibernateEimport org.hibernate.Simport org.hibernate.Timport com.mon.hibernate.HibernateUimport net.sf.cglib.proxy.Eimport net.sf.cglib.proxy.MethodIimport net.sf.cglib.proxy.MethodP/** * 使用CGLIB进行事务处理设置 * @author linbs */public class TransactionDAOProxy implements MethodInterceptor {private static Log logger = LogFactory.getLog(TransactionDAOProxy.class);private Enhancer enhancer=new Enhancer();public Object getDAO(Class clz){
enhancer.setSuperclass(clz);
enhancer.setCallback(this);
return enhancer.create();
}public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable {Session session =Transaction tx =Object result =try{session = HibernateUtil.getSession();tx = session.beginTransaction();result = proxy.invokeSuper(obj, args);tx.commit();session.flush();}catch(HibernateException e){try {tx.rollback();} catch (HibernateException e1) {logger.error(e1.getMessage());}}finally{try {HibernateUtil.closeSession();} catch (HibernateException e) {logger.error(e.getMessage());throw new Throwable("关闭session时出错!");}}}}在result = proxy.invokeSuper(obj, args);这个地方调用了未进行代理的dao类的方法;假设有个BaseHibernateDAO类 里面有这2个方法:/** * 取得当期进程的session对象 * @return */public Session getSession() {return HibernateUtil.getSession();}/** * 保存一个新的实体类的实例,并返回标识号 * @param obj * @return */public Serializable save(final Object obj) {return this.getSession().save(obj);}注意在save 方法中又调用了getSession()这个方法;现在来写一个测试类;package com.import com.mon.hibernate.BaseHibernateDAO;import com.linbs.usermanage.model.Upublic class Test {public static void main(String[] args){TransactionDAOProxy proxy = new TransactionDAOProxy();BaseHibernateDAO baseDAO = (BaseHibernateDAO)proxy.getDAO(BaseHibernateDAO.class);User user = new User();user.setUserName("abcProxy");user.setUserPwd("abcProxy");user.setEmail("");baseDAO.save(user);}}该测试类对BaseHibernateDAO的save方法进行了测试。这个代码貌似没错,但是在运行的时候抛出了如下错误:Exception in thread "main" org.hibernate.SessionException: Session is closed!at org.hibernate.impl.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:49)at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:526)at org.hibernate.impl.SessionImpl.save(SessionImpl.java:518)at org.hibernate.impl.SessionImpl.save(SessionImpl.java:514)at com.mon.hibernate.BaseHibernateDAO.save(BaseHibernateDAO.java:31)at com.mon.hibernate.BaseHibernateDAO$$EnhancerByCGLIB$$c88d447e.CGLIB$save$3(&generated&)at com.mon.hibernate.BaseHibernateDAO$$EnhancerByCGLIB$$c88d447e$$FastClassByCGLIB$$e5947bbb.invoke(&generated&)at net.sf.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:167)at com.test.TransactionDAOProxy.intercept(TransactionDAOProxy.java:49)at com.mon.hibernate.BaseHibernateDAO$$EnhancerByCGLIB$$c88d447e.save(&generated&)at com.test.Test.main(Test.java:21) 为什么? 经过测试,以及朋友的提醒,发现在BaseHibernateDAO的save()方法里调用了getSession()方法,而在运行的时候CGLIB会对getSession()和save()这2个方法都进行代理,因此在对save()进行tx.commit()和session.flush();的时候,在getSession()方法中已经进行了事务管理并关闭了session。唉!一不小心就踏入了陷阱。
最新教程周点击榜
微信扫一扫<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&

我要回帖

更多关于 java cglib 动态代理 的文章

 

随机推荐