CGLIB - dynamic bytecode generation

關鍵字:   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

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章