完整剖析SpringAOP的自調用
摘要:既然自調用的問題是由於SpringAOP由代理模式實現引起的,那就不使用代理模式不就解決了嗎。因爲使用了SpringAOP,所以會有代理模式的限制。
摘要
spring全家桶幫助java web開發者節省了很多開發量,提升了效率。但是因爲屏蔽了很多細節,導致很多開發者只知其然,不知其所以然,本文就是分析下使用spring的一些註解,不能夠自調用的問題。因爲本身這類文章很多,所以有些地方不會詳述,直接引用其他文章。
問題
-
使用了Spring中哪些註解不能進行自調用
-
爲什麼代理了就不能自調用
-
Spring常用的
@Cache
,@Async
,@Transaction
這三種原理上有什麼區別嗎 -
如何解自調用的問題
-
使用不同的解法各自有什麼坑
AOP的概述
首先需要澄清幾個需要區分的名詞 AOP
SpringAOP
AspectJ
AOP
Aspect-oriented programming,面向切面編程,一種解決問題的思想,將一些重複性的編碼問題通過切面來實現。很多人瞭解切面是通過Spring來了解的,所以會有種誤解將SpringAOP和AOP劃等號,其實不然。
Spring AOP
Spring AOP 算是 一種簡單的 AOP的落地實現方式,它主要提供在Spring容器內的一種AOP實現方式,脫離了Spring就不work了。Spring AOP並不是一套完整的AOP解決方案。
Spring的的衆多組件都是這樣,Spring-Session,Spring-jdbc,Spring-Cache等等,都能解決一部分通用的需求,但是會有很多限制, 想用深了,更靈活的實現功能,還是要使用其他的專業組件/框架。
SpringAOP默認使用代理模式實現的,也就是JDK Proxy/CGLib。關於代理以及JDK Proxy和CGLib不在贅述了。
AspectJ
Spring AOP並不是一套完整的AOP解決方案,AspectJ是的。AspectJ在編譯器織入切面到目標類
解法
上面介紹了SpringAop的實現,下面着重介紹解法。
方法1 - 注入代理bean到自己
這個原理沒啥好解析的
Note
會有循環依賴的問題,使用 @Lazy
解決
方法2 - AopContext.currentProxy()
獲取當前代理對象
使用
首先需要配置 @EnableAspectJAutoProxy(exposeProxy=true)
,允許代碼中獲取proxy類
原理解析
這個實現可以看下AopContext類,
然後就是Spring Aop自動設置代理,設置 exposeProxy
屬性的問題了。有人寫過了,就不寫了
https://cloud.tencent.com/developer/article/1497700
Note
-
因爲使用了SpringAOP,所以會有代理模式的限制
-
AopContext.currentProxy()使用的是ThreadLocal的,所以不能跨線程了
-
bean設置的限制,比如@Async代理創建方式不同其他|方式
方法3 - 直接使用AspectJ
既然自調用的問題是由於SpringAOP由代理模式實現引起的,那就不使用代理模式不就解決了嗎
使用
-
切換爲代理模式
-
添加aspectj織入包依賴
-
使用
-
啓動方式 AspectJ是編譯器將切面織入到目標class的,啓動的使用需要加上java agent的參數
總結
方法 | 限制 |
---|---|
自調用 | 代理模式的限制,比如只能作用於public ,非static的方法 |
AopContext.currentProxy() | 1. 代理模式的限制 2.ThreadLocal的限制,不能跨線程了 3.bean設置的限制,比如@Async代理創建方式不同其他 |
AspectJ | 無限制,使用起來麻煩一點 |
關注公衆號【方丈的寺院】,第一時間收到文章的更新,與方丈一起開始技術修行之路
參考
http://blog.kezhuw.name/2017/08/31/spring-aspectj-load-time-weaving/
https://cloud.tencent.com/developer/article/1497700
https://frightanic.com/software-development/spring-proxy-self-invocation/
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/ProxyAsyncConfiguration.html#asyncAdvisor--
https://www.baeldung.com/spring-aop-vs-aspectj