Spring是經過動態代理來實現AOP的,它有2種實現動態代理機制。java
關於JDK動態代理以前已經寫過了,這裏不在討論。spring
CGLib採用了很是底層的字節碼技術,其原理是經過字節碼技術爲一個類建立子類,並在子類中採用方法攔截的技術攔截全部父類方法的調用,順勢織入橫切邏輯。ide
Cglib代理,也稱做子類代理,它是在內存中構建一個子類對象從而實現對目標對象功能的擴展。工具
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(); } }
CGLib建立的動態代理對象性能比JDK建立的動態代理對象的性能高很多,可是CGLib在建立代理對象時所花費的時間卻比JDK多得多,因此對於單例的對象,由於無需頻繁建立對象,用CGLib合適,反之,使用JDK方式要更爲合適一些。同時,因爲CGLib因爲是採用動態建立子類的方法,對於final方法,沒法進行代理!this