public class AOPTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
A a = context.getBean(A.class);
a.a();
a.a1();
}
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
static class Config {
@Bean
public DefaultBeanFactoryPointcutAdvisor defaultBeanFactoryPointcutAdvisor() {
DefaultBeanFactoryPointcutAdvisor advisor = new DefaultBeanFactoryPointcutAdvisor();
advisor.setAdvice(testInterceptor());
NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
pointcut.setMappedNames("a","a1");
advisor.setPointcut(pointcut);
return advisor;
}
@Bean
public TestInterceptor testInterceptor(){
return new TestInterceptor();
}
@Bean
public A a1(){
return new A();
}
}
static class A {
public void a() {
System.out.println("aaaaaaaaaaa");
a1();
}
public void a1() {
System.out.println("aaaaaaaaaaa1");
}
}
static class TestInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("==========invoke=========");
return invocation.proceed();
}
}
}
Exception in thread "main" org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'AOPTest.Config': Bean with name 'AOPTest.Config' has been injected into other beans [defaultBeanFactoryPointcutAdvisor,testInterceptor] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:623)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:89)
Comment From: quaff
You should change the method name to any name except a
or a1
@Bean
public A a1(){
return new A();
}
Comment From: sbrannen
Hi @yiliou,
Thanks for getting in touch, but it feels like this is a question that would be better suited to Stack Overflow. As mentioned in the guidelines for contributing, we prefer to use the issue tracker only for bugs and enhancements. Feel free to update this issue with a link to the re-posted question (so that other people can find it) or add some more details if you feel this is a genuine bug.
The above is our formal policy regarding questions of this nature.
In any case, I can answer your question.
I've changed the title to "Why can't the method name intercepted by AOP be the same as an @Bean
method in an @Configuration
class?" to reflect what's actually going on in your example.
The answer is: your pointcut is too broad and attempts to advise the @Bean public A a1()
method in your @Configuration
class; whereas, I imagine you only meant to advise the methods in the A
class.
To fix that you need to add an appropriate ClassFilter
to the the pointcut. There are a few concrete implementations of ClassFilter
that you can choose from, or you can implement your own. To base the pointcut on methods in a given class (or subclasses thereof) you can use the RootClassFilter
.
The following changes make your code work without an exception.
@Bean
public DefaultBeanFactoryPointcutAdvisor defaultBeanFactoryPointcutAdvisor() {
DefaultBeanFactoryPointcutAdvisor advisor = new DefaultBeanFactoryPointcutAdvisor();
advisor.setAdvice(testInterceptor());
NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
pointcut.setMappedNames("a", "a1");
pointcut.setClassFilter(new RootClassFilter(A.class));
advisor.setPointcut(pointcut);
return advisor;
}
In light of that, I am closing this issue.
Comment From: yiliou
@sbrannen thanks