我正在學習AOP,在spring專案中,我有以下一段代碼。
MainDemoApp.java
public class MainDemoApp {
public static void main(String[] args) {
// read spring config java class
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(DemoConfig.class);
// DemoConfig.class is a simple class with just component scanning enabled
// and with @EnableAspectJAutoProxy
// get the bean from spring container
AccountDAO accountDAO = context.getBean("accountDAO", AccountDAO.class);
System.out.println(accountDAO.toString()); // line to be modified
// call the business method
accountDAO.addAccount();
// close the context
context.close();
}
}
AccountDAO.java
@Component
public class AccountDAO {
public void addAccount() {
System.out.println(this.toString()); // line to be modified
}
}
和我的方面課
MyDemoLoggingAspect.java
@Aspect
@Component
public class MyDemoLoggingAspect {
// this is where we add all our related advices for logging
// let's start with a @Before advice
@Before("execution(public void addAccount())")
public void beforeAddAccountAdvice() {
System.out.println("\n=======>>> Executing @Before Advice");
}
}
現在,當我運行main方法 in 時MainDemoApp,我得到以下輸出-輸出-
com.luv2code.aopdemo.dao.AccountDAO@3e0e1046
=======>>> Executing @Before Advice
com.luv2code.aopdemo.dao.AccountDAO@3e0e1046
正如你所看到的線條
System.out.println(accountDAO.toString());
和
System.out.println(this.toString());
給出相同的結果,before 通知也成功執行。默認情況下toString()定義為-
this.getClass().getName() "@" Integer.toHexString(this.hashCode())
但是當我明確列印出 getClass().getName() 結果是不同的
System.out.println(accountDAO.getClass().getName());
和
System.out.println(this.getClass().getName());
輸出-
com.luv2code.aopdemo.dao.AccountDAO$$EnhancerBySpringCGLIB$$88eb61b6
=======>>> Executing @Before Advice
com.luv2code.aopdemo.dao.AccountDAO
兩個班級名稱不同,我不知道那是哪種型別的班級名稱。同樣,當我明確列印時hashCode(),結果也不同。
我對獲得不同的結果感到困惑-
toString(),當toString()包括getClass().getName()和hashCode()getClass().getName()hashCode()
為什么會有這些差異,我沒有覆寫這些方法中的任何一個(最后),這是否與 AOP 代理有關?
Kindly help me clarify these doubts.
Edit-
I also have a very strange observation that when I modify
MainDemoApp.java
AccountDAO accountDAO = context.getBean("accountDAO", AccountDAO.class);
System.out.println(accountDAO.hashCode());
// call the business method
accountDAO.addAccount(accountDAO);
And AccountDAO.java is modified as-
public void addAccount(AccountDAO obj) {
System.out.println(this.hashCode() " " obj.hashCode());
}
NOW the result of hashCode() is the same but if I don't change the method signature and call hashCode() on the previous piece of code, the result is different
Can anyone explain this also?
uj5u.com熱心網友回復:
歡迎來到 SO。請注意,在這個平臺上,最好只問一個明確的問題,而不是很多。但我們也盡量對新手友好,所以我試著回答你的問題。雖然這有點多余,因為其他人已經在評論中回復了,我也認為評論是評論,答案是答案,即答案應該這樣寫。可能這里的其他貢獻者太忙了,無法寫出全面的答案,所以我在這里接球。
System.out.println(accountDAO.toString());和
System.out.println(this.toString());給出相同的結果
這是因為accountDAO是一個動態代理,并且您正在對其應用 Spring AOP 方面。它正在將方法呼叫轉發給它的委托(它代理的原始物件)。
但是當我明確列印出 getClass().getName() 結果是不同的
System.out.println(accountDAO.getClass().getName());和
System.out.println(this.getClass().getName());輸出-
com.luv2code.aopdemo.dao.AccountDAO$$EnhancerBySpringCGLIB$$88eb61b6 =======>>> Executing @Before Advice com.luv2code.aopdemo.dao.AccountDAO
前者列印CGLIB 代理類的名稱,后者列印目標類名稱。
同樣,當我明確列印時
hashCode(),結果也不同。
相同的原因:您正在列印代理與原始物件的哈希碼。
為什么會有這些差異,我沒有覆寫這些方法中的任何一個(最后),這是否與 AOP 代理有關?
嗯,在某種程度上你做到了。您應用了一個方面,導致代理創建。所以現在實際的 Spring bean 是一個代理,導致你上面描述的所有效果。從技術上講,Spring 代理是一個子類(或介面實作,取決于您的設定以及您是否代理介面或型別別)。代理保持對原始物件(其委托或目標物件)的參考,并用附加功能裝飾它。這是一個眾所周知的設計模式。Spring 在整個框架中大量使用它。有關更多詳細資訊,請參閱我的解釋here。
至于你的后續問題,根本原因和解釋同上。一旦您了解 Spring AOP 使用動態代理并且相同的代理使用委托來實作裝飾器模式,這一切都非常簡單和合乎邏輯。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/342752.html
標籤:java spring proxy aop aspect
下一篇:為集成測驗/@SpringBootTest提供bean時出現BeanDefinitionOverrideException
