首先让我说一下,我面临的问题是使用
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
Magician
和Volunteer
@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");
}
}
@Pointcut(execution(
方面的Magician
我在Spring config xml中有这两个项目
<context:component-scan base-package="com.underdogdevs.myspringaspectj" />
<aop:aspectj-autoproxy />
问题是来自
@Before
方面的Magician
未按预期打印。 我错过了什么吗?为什么不打印?我有其他方面的方法,没有参数,运行得很好。我没有正确传递参数值吗?
答案 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,@Bean
和AnnotationAwareAspectJAutoProxyCreator
声明都可能失败。
因此@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在它上面看不到任何注释。