为什么这个Spring Aspect不能用方法参数打印?

时间:2014-01-18 07:01:33

标签: java spring aop aspects

  

首先让我说一下,我面临的问题是使用 interceptThoughts(String thoughts)
方法,从第一个代码块开始,而不是打印

我正在运行来自 Spring in Action 的教程。有一个Magician课程,implements 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;
    }
}

该方面应该通过方法Volunteer

阅读implements 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;
    }
}

我的BeanConfig MagicianVolunteer

@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 config xml中有这两个项目

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

问题是来自@Before方面的Magician未按预期打印。 我错过了什么吗?为什么不打印?我有其他方面的方法,没有参数,运行得很好。我没有正确传递参数值吗?

2 个答案:

答案 0 :(得分:2)

Evgeniy有一个解决方案,我只想解释会发生什么。

指定

<aop:aspectj-autoproxy />
使用@Configuration

或注释@EnableAspectJAutoProxy类(您加载),Spring注册BeanPostProcessor<bean>

  

处理当前应用程序中的所有AspectJ注释方面   上下文,以及Spring Advisors。任何AspectJ注释类   将自动被识别,并且如果Spring,他们的建议适用   AOP的基于代理的模型能够应用它。

此过程的一个步骤包括寻找候选顾问。它通过扫描bean定义和检查bean类型来实现。这在发生任何bean之前发生,因此该过程只能依赖于已声明的内容。这是在猜测。

使用class声明,它通常不会成为问题,因为您将在@Bean属性中专门声明bean的类。

但是,使用<bean>方法,您可以指定一个接口。请注意,如果您使用工厂方法生成bean,@BeanAnnotationAwareAspectJAutoProxyCreator声明都可能失败。

因此@Bean查看上下文中的所有bean定义并猜测它们的类型。使用MindReader声明,它会查看方法的返回类型。

在您的情况下,返回类型将是@Aspect,它不是候选者,因为它没有@Bean注释。因此,不会应用任何建议(无代理),您将看不到您期望的行为。

可能的解决方案:

  • AnnotationAwareAspectJAutoProxyCreator更改返回类型,因此使Spring显而易见的是bean类型
  • 删除Magician定义,使用@Component为您的component-scan课程添加注释,并使其包裹为@Aspect。因为类型显然是带注释的类,所以Spring可以告诉它它也用BeanPostProcessor注释。

请注意,许多其他{{1}}实现都会猜测bean的类型。您必须知道在何时(初始化之前或之后)处理发生。

答案 1 :(得分:1)

试试这个

@Configuration
public class BeanConfig {

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

我不知道它是否在Spring的文档中,但很清楚当Spring分析返回类型为magician()时它是MindReader Spring在它上面看不到任何注释。