2014-01-18 45 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的那个;) –

相关问题