Spring之AOP動態代理實現的兩種方式

Spring是經過動態代理來實現AOP的,它有2種實現動態代理機制。java

  1. JDK動態代理。若是是有接口聲明的類進行AOP,spring調用的是java.lang.reflection.Proxy類來作處理
  2. CGLib動態代理。適合沒有接口聲明的類。

關於JDK動態代理以前已經寫過了,這裏不在討論。spring

1、關於CGLib

CGLib採用了很是底層的字節碼技術,其原理是經過字節碼技術爲一個類建立子類,並在子類中採用方法攔截的技術攔截全部父類方法的調用,順勢織入橫切邏輯。ide

Cglib代理,也稱做子類代理,它是在內存中構建一個子類對象從而實現對目標對象功能的擴展。工具

2、示例

Spring核心包中已經集成了Cglib,不須要另外導包。性能

package cn.iborder.factory;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import cn.iborder.Dao.IUserDao;
import cn.iborder.Dao.impl.UserDao;

/**
 * 實現Cglib的MethodInterceptor接口
 * @author iborder
 */
public class CglibProxyFactory implements MethodInterceptor {

	private Object target;	//目標對象
	
	public CglibProxyFactory(Object target) {
		this.target = target;
	}
	
	/**
	 * 返回代理對象
	 */
	public Object getProxyInstance() {
		//建立工具類
		Enhancer enhancer = new Enhancer();
		//設置父類
		enhancer.setSuperclass(target.getClass());
		//設置回調方法
		enhancer.setCallback(this);
		//建立代理對象(子類)
		return enhancer.create();
	}

	/**
	 * 回調方法
	 */
	@Override
	public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println(this.getClass().getSimpleName()+"代理對象附加的操做,執行前");						
		//mehtod表明目標對象被調用的方法名
		System.out.println(method.getName());
		// 執行目標對象方法
		Object result = method.invoke(target, args);
		System.out.println(this.getClass().getSimpleName()+"代理對象附加的操做,執行後");
		return result;
	}
	
	public static void main(String[] args) {
		IUserDao target = new UserDao();
		IUserDao userDao = (IUserDao) new CglibProxyFactory(target).getProxyInstance();
		userDao.findUsers();
	}

}

3、比較兩種方式的優缺點

CGLib建立的動態代理對象性能比JDK建立的動態代理對象的性能高很多,可是CGLib在建立代理對象時所花費的時間卻比JDK多得多,因此對於單例的對象,由於無需頻繁建立對象,用CGLib合適,反之,使用JDK方式要更爲合適一些。同時,因爲CGLib因爲是採用動態建立子類的方法,對於final方法,沒法進行代理!this

相關文章
相關標籤/搜索