在使用spring時,很多初學者不了解spring物件注入的機制和面向切面程式設計的原理,很容易犯一些錯誤。下面就是初學者最容易犯的錯誤。舉例如下:
@component
public class testclass
@scheduled(fixeddelay = 100)
public void task()}
這裡testclass類裡同時啟用了scheduled註解和@cacheable註解。如果在外面其他類中呼叫getdata(...)時,快取機制會生效,但是在task函式內部呼叫getdata(...)時,快取機制不會生效。網上有人把這歸納為:不能在同乙個類中互相呼叫註解過的方法,否則註解失效。
為什麼會有這樣的差別呢?背後的原因就是spring的物件注入機制。
當外部通過@autowired註解得到乙個testclass物件時,其實得到的是乙個spring包裝過的**物件。如下圖所示。
當呼叫obj.getdata時,實際呼叫的是spring的proxy物件中的getdata方法,該方法內建了cache機制,在cache檢查後就會呼叫實際的testclass物件中的getdata方法。
同理通過@scheduled註解表示這是乙個任務排程時,spring proxy物件中會初始化對應的排程執行緒池等工作,當觸發排程條件時,再呼叫實際的testclass物件。
但是當在實際的testclass物件中再呼叫getdata時,不會觸發cache機制,因為此時不是呼叫的springcacheproxy物件,而是乙個實際的testclass物件,所以不會觸發cache機制。
如果大家深入去讀spring完成注入和aop程式設計實現的原理,可以發現動態**是很重要的乙個技術。目前spring的動態**主要是通過cglib來實現的。後面我會再寫cglib的實現思路。
那麼我們該如何避免出現上述問題呢?
首先我們應該牢記乙個原則:同乙個類中的註解方法互相呼叫時,註解機制可能是無效的。
對於上述示例,我們可以把其拆分為兩個類來實現,乙個類完成任務排程、乙個類完成cache機制。這樣在任務排程中呼叫的是spring實現了cache機制的**類,可以確保其cache機制生效。
spring aop 同乙個bean中方法呼叫方法
component public class testbean transactional public void b a方法中呼叫b方法,b方法的事務是否生效!不生效 原因是spring會為testbean生成乙個 物件 testbeanproxy,只用呼叫testbeanproxy b 切面才會...
同乙個類中事務巢狀問題
解決辦法 把註解放到類上就可以了 原因 spring採用動態 aop 實現對bean的管理和切片,它為我們的每個class生成乙個 物件。只有在 物件之間進行呼叫時,可以觸發切面邏輯。而在同乙個class中,方法b呼叫方法a,呼叫的是原物件的方法,而不通過 物件。所以spring無法切到這次呼叫,也...
C 學習點滴(多次呼叫同乙個類)
在c 程式設計的時候,如果乙個類中的多個函式都呼叫同乙個類的函式,就應該在呼叫類中定義乙個被呼叫類的全域性例項,而不應該在每個函式中都定義乙個被呼叫類的例項。簡單的說,如果a類種的多個函式都呼叫b類的函式,則應該在a類中定義b類的全域性例項,詳見 int g nabc class b b g nab...