1. 程式人生 > >動態代理之

動態代理之

使用cglib實現動態代理

在上篇部落格java動態代理中我對java的動態代理進行了講解,但是我也說過,java的動態代理有一種缺點,那就是業務類必須要有介面,但是在實際情況中我們要橫切的業務類並不一定有介面,這個時候java的動態代理自然就不能使用了,為了解決這一問題,於是就出現了cglib,cglib可以說是很給力了,因為他的業務類有無介面皆可. 廢話不多說,上程式碼

  • 通過目標物件生成代理物件,通過cglib的api生成代理物件
/**
	 * 此類是一個工廠類
	 * 專門用來生成cglib的動態代理物件
	 * @author Administrator
	 */
	public class CGLIBProxy {
		/**
		
		 * @param targetObject 目標物件
		 * @return proxyObject 代理物件
		 *     proxyObject和targetObject是父子關係
		 *     targetObject所對應的目標類是父類,目標類不能是final修飾的
		 *     proxyObject所對應的類是子類(由cglib建立的代理類)
		 */
		public static Object getProxyObject(Object targetObject){
			Object proxyObject=null;
			//enhancer:增強,加強
			Enhancer enhancer=new Enhancer();
			//cglib動態代理有無介面皆可
			enhancer.setInterfaces(targetObject.getClass().getInterfaces());
			//設定代理類的父類
			enhancer.setSuperclass(targetObject.getClass());
			enhancer.setCallback(new TransactionInterceptor(targetObject));
			/*
			 * 用cglib來建立代理類,其底層cglib引用第三方功能jar asm.jar
			 * asm是一個java位元組碼生成框架,他是以二進位制形式修改已有的類,
			 * 來生成動態代理類的位元組碼,asm可以直接產生二進位制的class位元組碼檔案
			 * 也可以生成位元組碼在記憶體,\
			 * asm在建立class位元組碼,使用的是底層jvm的指令級別,所以建立位元組碼的時候
			 * 偏慢(相對於jdk生成位元組碼),但建立完的位元組碼,執行時cglib偏快(相對於jdk)
			 */
			proxyObject=enhancer.create();//用cglib來建立代理類
			return proxyObject;
		}
	}
  • 下面這個類是不是很熟悉,沒錯他就是耦合新舊業務而成的新的業務類,在執行的時候會通過回撥生成代理物件.
public class TransactionInterceptor implements MethodInterceptor{
		private Object targetObject;
		
		public TransactionInterceptor(Object targetObject) {
			this.targetObject = targetObject;
		}



		@Override
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object returnValue=null;
			TransactionManager tm=new TransactionManager();
			try{
				tm.begin();
				returnValue=method.invoke(targetObject, args);//用目標物件呼叫目標方法,returnValue是目標方法的返回值	
				//returnValue=methodProxy.invoke(targetObject, args);	
				tm.commit();
			}catch(Exception e){
				e.printStackTrace();
				tm.rollback();
			}
			
			return returnValue;
		}
	}

**

補充

**:本方法(intercept)的返回值不一定就是目標方法的返回值可以對目標方法的返回值做過其他的處理後,再通過本方法返回

講完了jdk的動態代理和cglib的動態代理,我們來對這兩種動態代理方式做一下總結 ****jdk和cglib的區別: jdk動態代理: 1.業務類必須有介面 2.必須實現InvocationHandler介面,在介面的子實現中耦合原有業務和新業務 3.代理類和業務類是兄弟關係,因為隸屬於同一個介面 4.用jdk建立代理,建立代理快,執行代理類慢 cglib動態代理: 1.業務類有無介面皆可 2.必須實現MethodInterceptor介面,在介面的子實現中耦合原有業務和新業務 3.代理類和業務類是父子,業務類是父,代理類是子 4.用asm和cglib建立代理類,建立慢,執行快 5.業務類不用final修飾

用jdk和cglib動態代理,在沒有特別java程式碼處理的前提下,是給業務類的所有方法橫切/織入新功能,spring aop自己建立了一套表示式語言,通過這些表示式,可以輕鬆控制業務類中的某些方法新增橫切,或不新增橫切,spring aop底層用的就是動態代理有業務介面用jdk動態代理,沒有業務介面用cglib動態代理