Deep Spring Boot: How to troubleshoot expected single matching bean but found 2 exception

Source: Internet
Author: User
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&gt, 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)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.