Java基礎之動態代理Cglib詳解
一、前言
經測試,jdk創建對象的速度遠大於cglib,這是由於cglib創建對象時需要操作字節碼。cglib執行速度略大於jdk,所以比較適合單例模式。另外由於CGLIB的大部分類是直接對Java字節碼進行操作,這樣生成的類會在Java的永久堆中。如果動態代理操作過多,容易造成永久堆滿,觸發OutOfMemory異常。spring默認使用jdk動態代理,如果類沒有接口,則使用cglib。
二、服務
package proxy.cglib; /** * @Description: <br/> * 訂單服務 * <p> * <br/> * @Author: Qz1997 * @create 2021/5/1 10:51 */ public class OrderServiceImpl { /** * 下單 * * @param orderNo 訂單號 * @return 結果 */ public String preOrder(String orderNo) { System.out.println("OrderServiceImpl.preOrder" + orderNo); return "下單成功"; } /** * 下單 * * @return 結果 */ public String list() { return "list"; } }
三、代理工廠
package proxy.cglib; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.Objects; /** * @Description: <br/> * Cglib 通過繼承的方式 實習代理 * final類 和 final 方法 不能代理 * <p> * <br/> * @Author: Qz1997 * @create 2021/5/1 13:24 */ public class CglibProxyFactory implements MethodInterceptor { /** * 創建一個代理對象 * * @param clazz 類型 * @return 代理對象 */ public Object creatProxyedObj(Class<?> clazz) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } /** * 代理方法 * * @param proxyObject 代理對象 * @param method 方法 * @param args 方法參數 * @param methodProxy 代理方法 * @return * @throws Throwable */ @Override public Object intercept(Object proxyObject, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { // 判斷方法參數 如果是null || 參數格式 <= 0 if (Objects.isNull(args) || args.length <= 0) { return methodProxy.invokeSuper(proxyObject, args); } /// // 判斷這個方法上是否包含某個註解 // if (method.isAnnotationPresent(Async.class)) { // // ....進行一頓增強 // // return method.invoke(proxy, arg); // } Parameter[] parameters = method.getParameters(); Parameter parameter = parameters[0]; Class<?> type = parameter.getType(); // 類型為String if (type == String.class) { String orderNo = (String) args[0]; if (Objects.nonNull(orderNo) && orderNo.length() < 10) { throw new RuntimeException("訂單號錯誤"); } } String result = (String) methodProxy.invokeSuper(proxyObject, args); if (Objects.equals(result, "下單成功")) { System.out.println("發動訂單短信"); } return result; } }
四、結果
到此這篇關於Java基礎之動態代理Cglib詳解的文章就介紹到這瞭,更多相關Java動態代理Cglib內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- java.lang.OutOfMemoryError: Metaspace異常解決的方法
- Spring AOP的底層實現方式-代理模式
- 解析動態代理jdk的Proxy與spring的CGlib(包括區別介紹)
- java面試常見模式問題—代理模式
- Java 動態代理的多種實現方式