代理模式之Cglib代理
阿新 • • 發佈:2018-11-30
Cglib代理,也叫做子類代理。在記憶體中構建一個子類物件從而實現對目標物件功能的擴充套件。
l JDK的動態代理有一個限制,就是使用動態代理的物件必須實現一個或多個介面。如果想代理沒有實現介面的類,就可以使用CGLIB實現。
l CGLIB是一個強大的高效能的程式碼生成包,它可以在執行期擴充套件Java類與實現Java介面。它廣泛的被許多AOP的框架使用,例如Spring AOP和dynaop,為他們提供方法的interception(攔截)。
l CGLIB包的底層是通過使用一個小而快的位元組碼處理框架ASM
Cglib子類代理:
1) 需要引入cglib – jar檔案, 但是spring的核心包中已經包括了cglib功能,所以直接引入spring-core-3.2.5.jar即可。
2)引入功能包後,就可以在記憶體中動態構建子類
3)代理的類不能為final, 否則報錯。
4) 目標物件的方法如果為final/static, 那麼就不會被攔截,即不會執行目標物件額外的業務方法。
在Spring的AOP程式設計中,
如果加入容器的目標物件有實現介面,用JDK代理;
如果目標物件沒有實現介面,用Cglib代理;
package loaderman.c_cglib;import java.lang.reflect.Method; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; /** * Cglib子類代理工廠 * (對UserDao 在記憶體中動態構建一個子類物件) * */ public class ProxyFactory implements MethodInterceptor{ // 維護目標物件 private Object target; public ProxyFactory(Object target){ this.target = target; } // 給目標物件建立代理物件 public Object getProxyInstance(){ //1. 工具類 Enhancer en = new Enhancer(); //2. 設定父類 en.setSuperclass(target.getClass()); //3. 設定回撥函式 en.setCallback(this); //4. 建立子類(代理物件) return en.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("開始事務....."); // 執行目標物件的方法 Object returnValue = method.invoke(target, args); System.out.println("提交事務....."); return returnValue; } }
package loaderman.c_cglib; /** * 目標物件 * */ public class UserDao { public void save() { System.out.println("-----已經儲存資料!!!------"); } }
package loaderman.c_cglib; public class App { public static void main(String[] args) { // 目標物件 UserDao target = new UserDao(); // class loaderman.c_cglib.UserDao System.out.println(target.getClass()); // 代理物件 UserDao proxy = (UserDao) new ProxyFactory(target).getProxyInstance(); // UserDao子類:class loaderman.c_cglib.UserDao$$EnhancerByCGLIB$$25d4aeab System.out.println(proxy.getClass()); // 執行代理物件的方法 proxy.save(); } }