2014-01-18 89 views
4

讓我先foremention,我面臨的問題是與
interceptThoughts(String thoughts)
方法,從第一個代碼塊,不打印爲什麼這個Spring Aspect不能像方法參數那樣打印?

我從春季行動中運行教程。有一個Magicianimplements MindReader接口方法interceptThoughts(String thoughts)getThoughts()

@Aspect 
public class Magician implements MindReader { 

    private String thoughts; 

    @Pointcut("execution(* com.underdogdevs.myspringaspectj." 
      + "Thinker.thinkOfSomething(String)) && args(thoughts)") 
    public void thinking(String thoughts) { 
    } 

    @Override 
    @Before("thinking(thoughts)") 
    public void interceptThoughts(String thoughts) { 
     System.out.println("Intercepting volunteer's thoughts : " + thoughts); 
     this.thoughts = thoughts; 
    } 

    @Override 
    public String getThoughts() { 
     return thoughts; 
    } 
} 

的方面是應該讀Volunteerimplements Thinker接口的頭腦,用方法thinkOfSomething(String thoughts)

public class Volunteer implements Thinker { 

    private String thoughts; 

    @Override 
    public void thinkOfSomething(String thoughts) { 
     this.thoughts = thoughts; 
     System.out.println("Something"); 
    } 

    public String getThoughts() { 
     return thoughts; 
    } 
} 

我有我的Java BeanConfigMagicianVolunteer

@Configuration 
public class BeanConfig { 

    @Bean 
    public MindReader magician() { 
     return new Magician(); 
    } 

    @Bean 
    public Thinker volunteer() { 
     return new Volunteer(); 
    } 
} 

而我試圖運行它來獲得Magician方法打印線的interceptThoughts方法

public class App { 
    public static void main(String[] args) { 
     ApplicationContext context = 
       new ClassPathXmlApplicationContext("spring-idol.xml"); 

     System.out.println(); 
     Thinker volunteer = (Thinker)context.getBean("volunteer"); 
     volunteer.thinkOfSomething("This is what I'm thinking"); 
    } 
} 

  • NO Eorrrs
  • 沒有例外
  • 包在@Pointcut(execution(Magician方面是正確的
  • 我有這兩個項目在我的Spring配置XML

    <context:component-scan base-package="com.underdogdevs.myspringaspectj" /> 
    <aop:aspectj-autoproxy /> 
    

的問題是從Magician方面@Before不打印,因爲它應該。 我在這裏錯過了什麼嗎?爲什麼不打印?我有其他方面的方法,沒有任何參數,運行得很好。我沒有正確傳遞參數值嗎?

+0

這可能是瘋狂的猜測,因爲你的方面對我來說似乎是正確的;你是否嘗試將志願者和魔術師註釋爲@ @ Component?或者將切入點放在@Before註釋中? –

+0

!guido我剛剛嘗試過,但它不起作用。我想這就是_this_' '用於在上下文中掃描bean的情況,而不是真正指定'@ Component' –

+0

,實際上'context:component-scan'是for掃描類*以搜索* @Component註釋(以及@Service,@Controller,...還有@Configuration,它是用@Component進行元註釋的) –

回答

1

試試這個

@Configuration 
public class BeanConfig { 

    @Bean 
    public Magician magician() { 
     return new Magician(); 
    } 
... 

,我不知道是否是在春天的文檔,但很明顯的是,當春analizes返回類型的magician()當它是MindReader春看不到任何註解它。

+0

您能解釋爲什麼這會起作用嗎?是否所有方面的bean都需要用這種方式來聲明,具體的類是什麼? –

+0

好的,看我的更新 –

2

Evgeniy有一個解決方案,我只是想解釋發生了什麼。

當指定

<aop:aspectj-autoproxy /> 

@EnableAspectJAutoProxy註釋一個@Configuration類(加載),彈簧註冊一個AnnotationAwareAspectJAutoProxyCreator其是BeanPostProcessor

處理所有的AspectJ註釋方面在當前應用 上下文以及Spring Advisors。任何AspectJ帶註釋的類 將自動被識別,並且如果Spring AOP的基於代理的模型能夠應用它,則應用其建議。

此過程的一個步驟包括尋找候選顧問。它通過掃描您的bean定義並檢查bean類型來實現。這發生在任何bean被創建之前,因此這個過程只能依賴已聲明的內容。這是猜測。

隨着<bean>聲明,它通常不會成爲一個問題,因爲你會專門聲明在class屬性中的bean的類。

但是,使用@Bean方法,您可以指定一個接口。請注意,如果使用工廠方法生成bean,則<bean>@Bean聲明可能都會失敗。

因此,AnnotationAwareAspectJAutoProxyCreator查看上下文中的所有bean定義並猜測它們的類型。使用@Bean聲明,它會查看該方法的返回類型。

就你的情況而言,返回類型將是MindReader由於它沒有@Aspect註釋,所以它不是候選者。因此,沒有建議(沒有代理)將被應用,你不會看到你期望的行爲。

可能的解決方案:

  • Evgeniy's solution改變返回類型,因此使其明顯到Spring bean的類型是什麼
  • 擺脫你@Bean定義,註解你Magician@Component,並有其包裝爲component-scan。因爲類型顯然是帶註釋的類,所以Spring將能夠告訴它也用@Aspect註解。

注意,許多其他BeanPostProcessor實現,猜bean的類型。你必須知道在哪一點(在初始化之前或之後)處理髮生。

+0

謝謝+3的那個;) –

相關問題