It 's written in front .
This demo demonstrates how to troubleshoot a common spring expected single matching bean but found 2 exception.
Https://github.com/hengyunabc/spring-boot-inside/tree/master/demo-expected-single Debugging Troubleshooting expected single Matching Bean but found 2 error
To import the project into the IDE and start the application directly, the exception information thrown is:
caused By:org.springframework.beans.factory.NoUniqueBeanDefinitionException:No qualifying bean of type ' Javax.sql.DataSource ' available:expected single matching beans but found 2:h2datasource1,h2datasource2 at ORG.SPRINGF Ramework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean (Defaultlistablebeanfactory.java : 1041) ~[spring-beans-4.3.9.release.jar:4.3.9.release] at Org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean (Defaultlistablebeanfactory.java : 345) ~[spring-beans-4.3.9.release.jar:4.3.9.release] at Org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean (Defaultlistablebeanfactory.java : ~[spring-beans-4.3.9.release.jar:4.3.9.release] At Org.springframework.context.support.AbstractApplicationContext.getBean (abstractapplicationcontext.java:1090) ~[ Spring-context-4.3.9.release.jar:4.3.9.release] At Org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.init (datasourceinitializer.java:71) ~[spring-boot-autoconfigure-1.4.7.release.jar:1.4.7.release] at Sun.reflect.NativeMethodAccessorImpl.invoke0 ( Native method) ~[na:1.8.0_112] at Sun.reflect.NativeMethodAccessorImpl.invoke (nativemethodaccessorimpl.java:62) ~[ NA:1.8.0_112] at Sun.reflect.DelegatingMethodAccessorImpl.invoke (delegatingmethodaccessorimpl.java:43) ~[na:1.8.0 _112] at Java.lang.reflect.Method.invoke (method.java:498) ~[na:1.8.0_112] at Org.springframework.beans.factory.ann Otation. Initdestroyannotationbeanpostprocessor$lifecycleelement.invoke (initdestroyannotationbeanpostprocessor.java:366 ) ~[spring-beans-4.3.9.release.jar:4.3.9.release] at org.springframework.beans.factory.annotation.initdestroyannotationbeanpostprocessor$ Lifecyclemetadata.invokeinitmethods (initdestroyannotationbeanpostprocessor.java:311) ~[ Spring-beans-4.3.9.release.jar:4.3.9.release] At Org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization (Initdestroyannotationbeanpostprocessor.java:134) ~[spring-beans-4.3.9.release.jar:4.3.9.release] ... Common frames omitted
A lot of people encounter this kind of mistake, the disposition is disorderly, can not find the method of the hand. In fact, the patient under investigation, is very simple. reason to throw an exception
The exception information is well written and needs to be injected/fetched to a DataSource bean in the spring context, but now there are two in the spring context, their names are: H2datasource1,h2datasource2
Then there are two questions: where the application is to inject/get to a datasource bean. Where the H2DATASOURCE1,H2DATASOURCE2 is defined. using the Java Exception breakpoint
In the IDE, create a new breakpoint, the type is Java Exception breakpoint (if you do not know how to add, you can search for the IDE's use of documents), the exception class is the above thrown out of the nouniquebeandefinitionexception.
When the breakpoint is stopped, look at the stack and you can clearly find it in Datasourceinitializer.init () line:71 here to get datasource:
Thread [main] (suspended (exception nouniquebeandefinitionexception)) owns:concurrenthashmap<k,v> (id=49) Owns:object (id=50) Defaultlistablebeanfactory.resolvenamedbean (class<t>, Object ...) line:1041 DefaultLis Tablebeanfactory.getbean (class<t>, Object ...) line:345 Defaultlistablebeanfactory.getbean (Class<T>) line:340 Annotationconfigembeddedwebapplicationcontext (Abstractapplicationcontext). GetBean (Class<T>) Line: 1090 Datasourceinitializer.init () line:71 nativemethodaccessorimpl.invoke0 (method, Object, object[]) line:not av ailable [Native Method] Nativemethodaccessorimpl.invoke (Object, object[)) line:62 delegatingmethodaccessorimpl.in Voke (object, object[]) line:43 Method.invoke (object, Object ...) line:498 initdestroyannotationbeanpostprocessor$ Lifecycleelement.invoke (Object) line:366 initdestroyannotationbeanpostprocessor$ Lifecyclemetadata.invokeinitmethods (Object, String) line:311 CommOnannotationbeanpostprocessor (initdestroyannotationbeanpostprocessor). Postprocessbeforeinitialization (Object, String) line:134 defaultlistablebeanfactory (abstractautowirecapablebeanfactory). Applybeanpostprocessorsbeforeinitialization (Object, String) line:409 defaultlistablebeanfactory (
abstractautowirecapablebeanfactory). Initializebean (String, Object, rootbeandefinition) line:1620 Defaultlistablebeanfactory (abstractautowirecapablebeanfactory). Docreatebean (String, Rootbeandefinition, Object[] ) line:555 defaultlistablebeanfactory (abstractautowirecapablebeanfactory). Createbean (String, RootBeanDefinition, Object[]) line:483 abstractbeanfactory$1.getobject () line:306 defaultlistablebeanfactory (DefaultSingletonBeanReg istry). Getsingleton (String, objectfactory<?>) line:230 defaultlistablebeanfactory (abstractbeanfactory). Dogetbean (String, Class<t>, object[], Boolean) line:302 defaultlistablebeanfactory (abstractbeanfactory). Getbean (String, Class<t>, Object ...) line:220 Defaultlistablebeanfactory.resolvenamedbean (class<t>, Object ...) line:1018 DEFAULTLISTABLEBEANFAC Tory.getbean (class<t>, Object ...) line:345 Defaultlistablebeanfactory.getbean (class<t>) line:340 Dat Asourceinitializerpostprocessor.postprocessafterinitialization (Object, String) line:62 defaultlistablebeanfactory
(abstractautowirecapablebeanfactory). Applybeanpostprocessorsafterinitialization (Object, String) line:423 Defaultlistablebeanfactory (abstractautowirecapablebeanfactory). Initializebean (String, Object, rootbeandefinition ) line:1633 defaultlistablebeanfactory (abstractautowirecapablebeanfactory). Docreatebean (String, Rootbeandefinition, object[]) line:555 defaultlistablebeanfactory (abstractautowirecapablebeanfactory). CreateBean ( String, Rootbeandefinition, object[]) line:483 abstractbeanfactory$1.getobject () line:306 DEFAULTLISTABLEBEANFAC Tory (Defaultsingletonbeanregistry). Getsingleton (StrinG, objectfactory<?>) line:230 defaultlistablebeanfactory (abstractbeanfactory). DoGetBean (String, Class<T ", object[], Boolean) line:302 defaultlistablebeanfactory (abstractbeanfactory). Getbean (String) line:197 Ltlistablebeanfactory.preinstantiatesingletons () line:761 Annotationconfigembeddedwebapplicationcontext (
Abstractapplicationcontext). Finishbeanfactoryinitialization (configurablelistablebeanfactory) line:867
Annotationconfigembeddedwebapplicationcontext (Abstractapplicationcontext). Refresh () line:543
Annotationconfigembeddedwebapplicationcontext (Embeddedwebapplicationcontext). Refresh () line:122 Springapplication.refresh (ApplicationContext) line:762 Springapplication.refreshcontext ( Configurableapplicationcontext) line:372 Springapplication.run (String ...) line:316 Springapplication.run (Object[ ], string[]) line:1187 springapplication.run (Object, String ...) line:1176 Demoexpectedsingleapplication.main (Str ing[]) LiNe:17
locate where to inject/use DataSource
To get datasource The specific code is:
Org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.init ()
@PostConstruct public
Void Init () {
if (!this.properties.isinitialize ()) {
logger.debug ("Initialization disabled" (not running DDL scripts )");
return;
}
if (This.applicationContext.getBeanNamesForType (Datasource.class, False,
false). length > 0) {
This.datasource = This.applicationContext.getBean (Datasource.class);
}
if (This.datasource = = null) {
logger.debug ("No DataSource found so not initializing");
return;
}
Runschemascripts ();
}
This.applicationContext.getBean (Datasource.class); Requires that there be only one datasource bean in the spring context, but there are two applications, so the nouniquebeandefinitionexception is thrown. to get the code that the bean specifically defines from beandefinition
Let's look at where H2datasource1,h2datasource2 is defined.
The above process is broken in the Defaultlistablebeanfactory.resolvenamedbean (class<t>, Object ...) function throw new Nouniquebeandefinitionexception (Requiredtype, Candidates.keyset ()); This line.
So let's do this here (if not clear, search the IDE for how to execute the code in the breakpoint case):
This.getbeandefinition ("H2datasource1")
The information returned is:
Root bean:class [NULL]; scope=; Abstract=false; Lazyinit=false; autowiremode=3; dependencycheck=0; Autowirecandidate=true; Primary=false; Factorybeanname=demoexpectedsingleapplication; Factorymethodname=h2datasource1; Initmethodname=null; Destroymethodname= (inferred);
Defined in Com.example.demo.expected.single.DemoExpectedSingleApplication
Can be clearly positioned to h2datasource1 this bean is defined in com.example.demo.expected.single.DemoExpectedSingleApplication.
So the answer to the above two questions is: Datasourceinitializer.init () in the spring boot code line:71 here to get DataSource, and only one datasource instance is allowed H2DATASOURCE1,H2DATASOURCE2 is defined in com.example.demo.expected.single.DemoExpectedSingleApplication to solve the problem .
The reason for this is that the application defines two datasource instances, but spring boot requires only one. There are two ways to fix this: use @primary to specify a preferred datasource, so that the automatically initialized code in the spring boot will get the @primary bean to take spring Boot automatically initializes datasource related code is prohibited, apply yourself to control all datasource related beans
There are two ways of banning:
Configure exclude on the main function
@SpringBootApplication (exclude = {Datasourceautoconfiguration.class, Datasourcetransactionmanagerautoconfiguration.class})
Configure in Application.properties:
Spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.datasourceautoconfiguration, Org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
Summary When troubleshooting spring initialization issues, flexible use of Java Exception Breakpoint from the exception stack makes it easy to find out where to inject/use beans From beandefinition you can find out where the bean is defined (which configuration class/xml)