91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

springboot2.x中默認使用代理是cglib代理的操作示例

發布時間:2021-08-09 11:44:19 來源:億速云 閱讀:152 作者:小新 欄目:開發技術

小編給大家分享一下springboot2.x中默認使用代理是cglib代理的操作示例,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

背景

因為項目優化,打算寫個日志的切面類,于是起了個springboot 工程,在這里面測試。結果在springboot 里面測試正常,能正確打印日志,但是把代碼復制到實際項目中,在進入切面打印日志的時候總是報錯,報空指針錯誤。

經調試發現每次都是在獲取注解上的屬性時報錯。當時百思不得解。后來靈光一閃,想到可能是項目中獲取到的是接口方法,而springboot是實現類的method ,所以可以拿到注解的屬性。

但是仔細一想,Springboot里面也是接口,難道不應該走JDK動態代理嗎?那拿到這個方法的應該也是接口的方法,帶著這個疑問,我開始了我的探索之旅。

驗證

springboot 項目

springboot2.x中默認使用代理是cglib代理的操作示例

spring 項目

springboot2.x中默認使用代理是cglib代理的操作示例

發現springBoot 竟然走的是cglib代理,起代理的是實現類,所以能拿到方法上注解的屬性,而我的項目是個傳統的spring 項目,service是接口,走的是JDK動態代理,通過切點拿到的是接口的方法,而接口上又沒有注解,所以按照springboot的寫法是拿不到注解的,拿不到注解也就拿不到注解屬性,所以報錯。

解決辦法

springboot的寫法

 private Method getMethod(ProceedingJoinPoint joinPoint) throws NoSuchMethodException {
        //獲取方法簽名
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        return method;
    }
    
 private String getAnnotationDesc(ProceedingJoinPoint joinPoint) throws NoSuchMethodException {
        Method method = getMethod(joinPoint);
        String value = method.getAnnotation(MyLog.class).value();
        return value;
    }

spring 的寫法

private Method getMethod(ProceedingJoinPoint joinPoint) throws NoSuchMethodException {
        //獲取方法簽名
        Class<?> targetClass = joinPoint.getTarget().getClass();
        String methodName = joinPoint.getSignature().getName();
        Class[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
        Method method = targetClass.getMethod(methodName, parameterTypes);
        return method;
    }
private String getAnnotationDesc(ProceedingJoinPoint joinPoint) throws NoSuchMethodException {
        Method method = getMethod(joinPoint);
        String value = method.getAnnotation(MyLog.class).value();
        return value;
    }

可以看到spring項目的方法是先獲取目標類,然后再通過目標類獲取目標方法,然后再獲取方法上的注解。

深度追蹤

springboot 為什么將默認的代理改成了cglib,這會導致什么問題?如果我們想要事務走JDK動態代理,該如何做?

帶著這些疑問,我翻閱了springboot的相關issue ,發現很多人提這個問題。

先關issue如下:

issue1

issue2

issue2

springboot團隊之所以默認的代理模式設置成cglib代理,看看spring的官方團隊是怎么解釋的

This was changed in 1.4 (see 5423). We've generally found cglib proxies less likely to cause unexpected cast exceptions.

他們認為使用cglib更不容易出現轉換錯誤。springboot 默認的配置文件的位置在

/org/springframework/boot/spring-boot-autoconfigure/2.1.7.RELEASE/spring-boot-autoconfigure-2.1.7.RELEASE.jar!/META-INF/spring-configuration-metadata.json

{
      "name": "spring.aop.proxy-target-class",
      "type": "java.lang.Boolean",
      "description": "Whether subclass-based (CGLIB) proxies are to be created (true), as opposed to standard Java interface-based proxies (false).",
      "defaultValue": true
    },

如果在事務中強制使用JDK動態代理,以往的知識告訴我們,我們需要將proxyTargetClass 設置成false,于是我們在springboot 中發現注解@EnableTransactionManagement 或者@EnableAspectJAutoProxy默認就為false,說明這里面的屬性不起作用

@EnableAspectJAutoProxy(proxyTargetClass = false)
@EnableTransactionManagement(proxyTargetClass = false)

同理 @EnableCaching 上的proxyTargetClass 屬性也是失效的。如果偏要springboot 走JDK動態代理,那么需要在application.properties里面配置

spring.aop.proxy-target-class=false

此時項目中走的就是JDK動態代理。

以上是“springboot2.x中默認使用代理是cglib代理的操作示例”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

会理县| 平顺县| 永泰县| 桓台县| 双辽市| 大同市| 东阿县| 高唐县| 通化县| 香格里拉县| 平安县| 红安县| 尼玛县| 莱阳市| 丰原市| 滕州市| 婺源县| 西宁市| 额敏县| 犍为县| 江山市| 个旧市| 成安县| 鄂州市| 河北区| 余姚市| 泰和县| 资源县| 衡南县| 义马市| 丹江口市| 茂名市| 遵义市| 梧州市| 江华| 晋中市| 大姚县| 钦州市| 民县| 平邑县| 迁西县|