Reputation: 10511
In my Spring application I have defined a bean of type AuditListener
.
@Component
public class AuditListener {
}
My project also contains a dependency to spring-boot-starter-actuator
which also defines a bean of type AuditListener
via AuditAutoConfiguration
.
When I try to start my application it fails because my own AuditListener
is not available.
// successful
beanFactory.getBean(org.springframework.boot.actuate.audit.listener.AuditListener.class);
// fails with NoSuchBeanDefinitionException
beanFactory.getBean(demo.AuditListener.class);
Exception:
java.lang.IllegalStateException: Failed to execute ApplicationRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:791)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:778)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1255)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1243)
at demo.DemoApplication.main(DemoApplication.java:14)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'demo.AuditListener' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:347)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:334)
at demo.DemoApplication.run(DemoApplication.java:27)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:788)
... 11 more
The DefaultListableBeanFactory logs
INFO 10140 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Overriding bean definition for bean 'auditListener' with a different definition: replacing [Generic bean: class [demo.AuditListener]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [C:\workspace\spring-autoconfiguration-conflict-demo\target\classes\demo\AuditListener.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.actuate.autoconfigure.audit.AuditAutoConfiguration; factoryMethodName=auditListener; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/actuate/autoconfigure/audit/AuditAutoConfiguration.class]]
How can I get both AuditListener
beans into my context without renaming my own?
edit: If I define two beans with same class name in different packages I get a ConflictingBeanDefinitionException, so the ApplicationContext won't even start.
Upvotes: 2
Views: 1696
Reputation: 61
If a bean with the same bean name is added by an AutoConfiguration, Spring would remove your own bean from the context. That’s standard Spring Framework behaviour. When there are multiple beans declared with the same name, the last one that’s declared will win. Framework should log an info message to let you know that an override has taken place.
Upvotes: 0
Reputation: 15854
You can give a name to your bean so that it will not conflict with the SpringBoot
bean
@Component(value = "myCustomAuditListener ")
public class AuditListener {
}
and then use @Qualifies
to inject it by name myCustomAuditListener
Upvotes: 1