CGLIB (Code Generation Library) 是一個動態字節碼生成庫, 基於ASM, 使用時需要asm.jar。(Groovy也是使用ASM來生成java的字節碼)
使用java的java.lang.reflect.Proxy只能針對接口生成代理; 而使用CGLIB則可以針對類生成代理. CGLIB原理是在運行時動態生成一個被代理類的子類。
下面的例子使用CGLIB, 對服務層對象的方法進行攔截,實現一個類似的AOP.
java 代碼
- public class ProductService implements ServiceInterface
{
-
- public void doDelete(Integer id) {
- productDAO.delete(id);
- }
-
- public void doSave(ProductDTO dto) {
- productDAO.saveOrUpdate(dto);
- }
-
- public void doUpdate(ProductDTO dto) {
- productDAO.saveOrUpdate(dto);
- }
-
- public ProductDTO getObject(Integer id) {
- return productDAO.getProduct(id);
- }
- }
ProductService是一個簡單的服務層類, 在ServiceInterface中定義了DAO對象和一些方法。
如果服務層對象有事物方面的需要, 就使用Interceptor來增強. 需要實現 net.sf.cglib.proxy.MethodInterceptor 接口.
java 代碼
- public class ServiceMethodInterceptor implements MethodInterceptor {
-
- private static final Logger logger = Logger.getLogger(ServiceMethodInterceptor.class);
-
- public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
-
- if (method == null || StringUtils.isBlank(method.getName())) {
- logger.error("Method is null!");
- return null;
- }
- String methodName = method.getName();
-
-
- if (methodName.startsWith("do")) {
- return updateTransaction(o, method, args, proxy);
- }
-
-
- if (methodName.startsWith("get")) {
- return queryTransaction(o, method, args, proxy);
- }
-
- return proxy.invokeSuper(o,args);
- }
-
- private Object queryTransaction(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
-
- Object result = null;
- try{
- result = proxy.invokeSuper(o,args);
- } catch (Exception e) {
- logger.fatal(e);
- } finally {
- TransactionBO.endSession();
- }
-
- return result;
- }
-
- private Object updateTransaction(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
-
- Object result = null;
- try{
- TransactionBO.beginTransaction();
- result = proxy.invokeSuper(o,args);
- TransactionBO.commit();
- } catch (Exception e) {
- TransactionBO.rollback();
- } finally {
- TransactionBO.endSession();
- }
-
- return result;
- }
-
- }
java 代碼
- public class ServiceFactory {
-
- public static extends ServiceInterface> T getServiceInstance(Class clazz) {
- Enhancer enhancer = new Enhancer();
- enhancer.setSuperclass(clazz);
- enhancer.setCallback(new ServiceMethodInterceptor());
- return (T) enhancer.create();
- }
- }
使用ProductService時,需要由ServiceFactory創建
java 代碼
- public static void main(String[] args) {
- ProductService productService = ServiceFactory.getServiceInstance(ProductService.class);
- productService.doSave(...);
- productService.getObject(...);
- }
實際上這裏使用的是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
|