Cglib代理,也叫作子類代理。在內存中構建一個子類對象從而實現對目標對象功能的擴展。java
比較:spring
JDK的動態代理有一個限制,就是使用動態代理的對象必須實現一個或多個接口。若是想代理沒有實現接口的類,就能夠使用CGLIB實現。編程
CGLIB是一個強大的高性能的代碼生成包,它能夠在運行期擴展Java類與實現Java接口。它普遍的被許多AOP的框架使用,例如Spring AOP和dynaop,爲他們提供方法的interception(攔截)。markdown
CGLIB包的底層是經過使用一個小而快的字節碼處理框架ASM,來轉換字節碼並生成新的類。不鼓勵直接使用ASM,由於它要求你必須對JVM內部結構包括class文件的格式和指令集都很熟悉。框架
Cglib子類代理:ide
1)須要引入cglib – jar文件,可是spring的核心包中已經包括了cglib功能,因此直接添加spring-core的依賴便可工具
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.10.RELEASE</version> </dependency>
2)引入功能包後,就能夠在內存中動態構建子類性能
3)代理的類不能爲final, 不然報錯。測試
4) 目標對象的方法若是爲final/static,那麼就不會被攔截,即不會執行目標對象額外的業務方法。this
在Spring的AOP編程中,
若是加入容器的目標對象有實現接口,用JDK代理;
若是目標對象沒有實現接口,用Cglib代理;
下面開始CGLIB代理的示例
先寫一個UserDao
package xin.sun.proxy.cglib; /** * @author Ginkgo */ public class UserDao { public void save() { System.out.println("UserDao . save"); } }
再寫一個代理工廠ProxyFactory,實現CGLIB中的MethodInterceptor接口
package xin.sun.proxy.cglib; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * @author Ginkgo */ public class ProxyFactory implements MethodInterceptor { /** * 被代理對象 */ private Object target; /** * 構造器 * * @param target */ public ProxyFactory(Object target) { this.target = target; } /** * 獲取代理對象實例 * * @return Object 代理對象實例 */ public Object getProxyInstance() { /** * 工具類 */ Enhancer enhancer = new Enhancer(); /** * 設置父類 */ enhancer.setSuperclass(target.getClass()); /** * 設置回調對象 */ enhancer.setCallback(this); /** * 建立子類代理對象,並返回 */ return enhancer.create(); } /** * 重寫攔截方法 * * @param o 代理對象 * @param method 委託類方法 * @param objects 方法參數 * @param methodProxy 代理方法的MethodProxy對象 * @return Object 目標方法執行結果 * @throws Throwable */ @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("開始事務..."); /** * 方法執行結果 */ Object result = method.invoke(target,objects); System.out.println("結束事務..."); return result; } }
再寫一個入口類Portal來測試
package xin.sun.proxy.cglib; /** * @author Ginkgo */ public class Portal { public static void main(String[] args) { ProxyFactory proxyFactory = new ProxyFactory(new UserDao()); UserDao proxyInstance = (UserDao) proxyFactory.getProxyInstance(); proxyInstance.save(); } }
運行結果:
開始事務... UserDao . save 結束事務...
而後再看看JDK動態代理
先寫一個接口IOrderDao和實現類OrderDaoImpl
package xin.sun.proxy.dynamic; /** * @author Ginkgo */ public interface IOrderDao { /** * 保存對象 * * @param obj */ void save(Object obj); } ----------------------------------------------------------------------------------------------------- package xin.sun.proxy.dynamic; /** * @author Ginkgo */ public class OrderDaoImpl implements IOrderDao { @Override public void save(Object obj) { System.out.println("OrderDaoImpl -> save " + obj); } }
再寫一個代理工廠ProxyFactory,實現InvocationHandler接口
package xin.sun.proxy.dynamic; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * @author Ginkgo */ public class ProxyFactory implements InvocationHandler { /** * 被代理對象 */ private Object target; /** * 構造器 * * @param target */ public ProxyFactory(Object target) { this.target = target; } /** * desc:獲取代理對象 * * @return java.lang.Object * @author Ginkgo */ public Object getProxyInstance() { Object proxyInstance = Proxy .newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this); return proxyInstance; } /** * 重寫調用方法 * * @param proxy * @param method * @param args * @return Object 方法執行結果 * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("開始事務 ..."); Object result = method.invoke(target, args); System.out.println("結束事務 ..."); return result; } }
在寫一個Portal入口類測試一下
package xin.sun.proxy.dynamic; /** * @author Ginkgo */ public class Portal { public static void main(String[] args) { ProxyFactory proxyFactory = new ProxyFactory(new OrderDaoImpl()); IOrderDao proxyInstance = (IOrderDao) proxyFactory.getProxyInstance(); proxyInstance.save("test"); } }
運行結果
開始事務 ... OrderDaoImpl -> save test 結束事務 ...