CGLIB - dynamic bytecode generation

原创 2007年10月14日 19:28:00
关键字:   cglib    

CGLIB (Code Generation Library) 是一个动态字节码生成库, 基于ASM, 使用时需要asm.jar。(Groovy也是使用ASM来生成java的字节码)

使用java的java.lang.reflect.Proxy只能针对接口生成代理; 而使用CGLIB则可以针对类生成代理. CGLIB原理是在运行时动态生成一个被代理类的子类。

下面的例子使用CGLIB, 对服务层对象的方法进行拦截,实现一个类似的AOP.

java 代码
  1. public class ProductService implements ServiceInterface  {   
  2.        
  3.     public void doDelete(Integer id) {   
  4.         productDAO.delete(id);   
  5.     }   
  6.   
  7.     public void doSave(ProductDTO dto) {   
  8.         productDAO.saveOrUpdate(dto);   
  9.     }   
  10.   
  11.     public void doUpdate(ProductDTO dto) {   
  12.         productDAO.saveOrUpdate(dto);   
  13.     }   
  14.   
  15.     public ProductDTO getObject(Integer id) {   
  16.         return productDAO.getProduct(id);   
  17.     }   
  18. }  

ProductService是一个简单的服务层类, 在ServiceInterface中定义了DAO对象和一些方法。

如果服务层对象有事物方面的需要, 就使用Interceptor来增强. 需要实现 net.sf.cglib.proxy.MethodInterceptor 接口.

java 代码
  1. public class ServiceMethodInterceptor implements MethodInterceptor {   
  2.        
  3.     private static final Logger logger = Logger.getLogger(ServiceMethodInterceptor.class);   
  4.   
  5.     public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {   
  6.   
  7.         if (method == null || StringUtils.isBlank(method.getName())) {   
  8.             logger.error("Method is null!");   
  9.             return null;   
  10.         }   
  11.         String methodName = method.getName();   
  12.            
  13.         //所有以do开头的方法,使用updateTransaction   
  14.         if (methodName.startsWith("do")) {   
  15.             return updateTransaction(o, method, args, proxy);   
  16.         }   
  17.            
  18.         //所有以get开头的方法,使用queryTransaction   
  19.         if (methodName.startsWith("get")) {   
  20.             return queryTransaction(o, method, args, proxy);   
  21.         }   
  22.            
  23.         return proxy.invokeSuper(o,args);   
  24.     }   
  25.        
  26.     private Object queryTransaction(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {   
  27.   
  28.         Object result = null;   
  29.         try{   
  30.             result = proxy.invokeSuper(o,args);   
  31.         } catch (Exception e) {   
  32.             logger.fatal(e);   
  33.         }  finally {   
  34.             TransactionBO.endSession();   
  35.         }   
  36.            
  37.         return result;   
  38.     }   
  39.        
  40.     private Object updateTransaction(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {   
  41.            
  42.         Object result = null;   
  43.         try{   
  44.             TransactionBO.beginTransaction();   
  45.             result = proxy.invokeSuper(o,args);   
  46.             TransactionBO.commit();   
  47.         } catch (Exception e) {   
  48.             TransactionBO.rollback();   
  49.         }  finally {   
  50.             TransactionBO.endSession();   
  51.         }   
  52.            
  53.         return result;   
  54.     }   
  55.   
  56. }  
java 代码
  1. public class ServiceFactory {   
  2.        
  3.     public static extends ServiceInterface> T getServiceInstance(Class clazz) {   
  4.         Enhancer enhancer = new Enhancer();   
  5.         enhancer.setSuperclass(clazz);   
  6.         enhancer.setCallback(new ServiceMethodInterceptor());   
  7.         return (T) enhancer.create();   
  8.     }   
  9. }  

使用ProductService时,需要由ServiceFactory创建

java 代码
  1. public static void main(String[] args) {   
  2.     ProductService productService = ServiceFactory.getServiceInstance(ProductService.class);   
  3.     productService.doSave(...);   
  4.     productService.getObject(...);   
  5. }  

实际上这里使用的是CGLIB生成的ProductService的子类.  Enhancer生成的子类都实现了net.sf.cglib.proxy.Factory接口, 可以通过Factory.getCallbacks()取回MethodInterceptor

参考

http://cglib.sourceforge.net/

http://asm.objectweb.org/

http://www.javaeye.com/topic/98178

http://www.blogjava.net/calvin/archive/2005/11/28/21741.html

http://www-128.ibm.com/developerworks/cn/java/j-dyn0414/index.html

 

在Hibernate3.3应用中把默认使用的javassist更换为cglib

 在Hibernate3.3版本中,使用的字节码增强包默认是javassist了。而在3.2.6中默认使用的是cglib。要在3.3中更换为cglib,需要进行如下操作: 1. 在classpath下...
  • qjyong
  • qjyong
  • 2009-10-29 23:09:00
  • 5141

深入了解Java ClassLoader、Bytecode 、ASM、cglib

一、Java ClassLoader 1,什么是ClassLoader 与 C 或 C++ 编写的程序不...
  • lcj8
  • lcj8
  • 2008-03-25 23:16:00
  • 2075

axis2+spring+hibernate(webservice工程)

使用axis2+spring+hibernate三大框架整合构建webservice工程,一遍遍的修改配置文件,一遍遍的调试,费了好一番功夫终于成功了,可以实现对数据库的操作了,任务还要求使用事务,添...
  • fengyun111999
  • fengyun111999
  • 2010-07-21 18:11:00
  • 4776

CGLIB Enhancement failed 解决方法

今天做ssh项目时碰到报这个错: org.hibernate.HibernateException: CGLIB Enhancement failed: com.medicom.lcsy.model...
  • meryvn
  • meryvn
  • 2012-09-19 15:29:39
  • 3791

Dynamic proxy与 CGLib 的区分

Spring 动态代理分为:Dynamic proxy(针对实现了接口的类)和cglib(针对实现了无接口的类)。        CGLib与Dynamic Proxy的代理机制基本类似,Dynam...
  • chaosbea
  • chaosbea
  • 2012-10-27 11:10:49
  • 191

springboot CGLib 方式实现AOP代理问题

在Spring Boot中引入AOP就跟引入其他模块一样,非常简单,只需要在pom.xml中加入如下依赖: org.springframework.boot spring-boot-s...
  • huang_550
  • huang_550
  • 2016-12-15 16:46:07
  • 8732

release3.1

  • 2017年11月21日 18:27
  • 247KB
  • 下载

直播预告:基于动态词表的对话生成研究 | PhD Talk #21

「PhD Talk」是 PaperWeekly 的学术直播间,旨在帮助更多的青年学者宣传其最新科研成果。我们一直认为,单向地输出知识并不是一个最好的方式,而有效地反馈和交流可能会让知识的传播更加有意义...
  • c9Yv2cf9I06K2A9E
  • c9Yv2cf9I06K2A9E
  • 2017-12-26 00:00:00
  • 363

JDK、CGLIB、Spring三种实现代理的区别(二)CGLIB中proxy动态代理

CGLIB中的动态代理是JDK proxy的一个很好的补充,在JDK中实现代理时,要求代理类必须是继承接口的类,因为JDK最后生成的proxy class其实就是实现了被代理类所继承的接口并且继承了j...
  • sunnycoco05
  • sunnycoco05
  • 2017-12-20 14:47:08
  • 76

当我们谈论「Chatbot」时,我们在读什么? | 论文集精选 #05

PaperWeekly 是一个 AI 学术分享社区。这里聚集了大批一线 AI 学者,他们用精炼妙语推荐各自发现的优质论文。 点击本文底部的「阅读原文」即刻加入社区,创建属于你的论文集。 这...
  • c9Yv2cf9I06K2A9E
  • c9Yv2cf9I06K2A9E
  • 2017-12-08 00:00:00
  • 212
收藏助手
不良信息举报
您举报文章:CGLIB - dynamic bytecode generation
举报原因:
原因补充:

(最多只允许输入30个字)