Spring Boot Embedded Tomcat - 没有 'javax.sql.DataSource' 类型的合格 bean 可用:预期单个匹配 bean 但找到 3

Spring Boot Embedded Tomcat - No qualifying bean of type 'javax.sql.DataSource' available: expected single matching bean but found 3

我正在开发我的 spring 启动应用程序和 运行 嵌入式 tomcat 8.x。我正在尝试使用 JNDI 配置三个不同的 oracle 数据源并遵循此 link。以下是我的不同文件:

申请-dev.properties

spring.oracle.datasource.oracleDS1.jndi-name=jdbc/oracleDS1
spring.oracle.datasource.oracleDS2.jndi-name=jdbc/oracleDS2
spring.oracle.datasource.oracleDS3.jndi-name=jdbc/oracleDS3

OracleDataSourceConfiguration

package com.adp.orbis.requesttracker.orbisrequesttracker;

import javax.sql.DataSource;

    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.context.annotation.Profile;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup;

    @Configuration
    public class OracleDataSourceConfiguration {

        @Value("${spring.oracle.datasource.oracleDS1.jndi-name}")
        private String oracleDS1;

        @Value("${spring.oracle.datasource.oracleDS2.jndi-name}")
        private String oracleDS2;

        @Value("${spring.oracle.datasource.oracleDS3.jndi-name}")
        private String oracleDS3;

        @Bean(name="dataSource1", destroyMethod = "")
        @Profile("dev")
        @Primary
        public DataSource evolutionDataSource() {
            JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
            return dataSourceLookup.getDataSource(oracleDS1);
        }

        @Bean(name="dataSource2", destroyMethod = "")
        @Profile("dev")
        @Primary
        public DataSource orbisQueryOnlyDataSource() {
            JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
            return dataSourceLookup.getDataSource(oracleDS2);
        }

        @Bean(name="dataSource3", destroyMethod = "")
        @Profile("dev")

        public DataSource orbisExportDataSource() {
            JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
            return dataSourceLookup.getDataSource(oracleDS3);
        }
    }

TomcatEmbeddedServletContainerFactory

@Bean
    public TomcatEmbeddedServletContainerFactory tomcatFactory() {
        return new TomcatEmbeddedServletContainerFactory() {

            @Override
            protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) {
                tomcat.enableNaming();
                return super.getTomcatEmbeddedServletContainer(tomcat);
            }

            @Override
            protected void postProcessContext(Context context) {
                ContextResource oracleDS1JNDIResource = new ContextResource();
                oracleDS1JNDIResource.setName("jdbc/oracleDS1");
                oracleDS1JNDIResource.setType(DataSource.class.getName());
                oracleDS1JNDIResource.setProperty("driverClassName", "oracle.jdbc.driver.OracleDriver");
                oracleDS1JNDIResource.setProperty("url", "jdbc:oracle:thin:@localhost:1521/mydbservice1");
                oracleDS1JNDIResource.setProperty("username", "db-user-name");
                oracleDS1JNDIResource.setProperty("password", "db-user-pass");
                oracleDS1JNDIResource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");
                context.getNamingResources().addResource(oracleDS1JNDIResource);

                ContextResource oracleDS2JNDIResource = new ContextResource();
                oracleDS2JNDIResource.setName("jdbc/oracleDS2");
                oracleDS2JNDIResource.setType(DataSource.class.getName());
                oracleDS2JNDIResource.setProperty("driverClassName", "oracle.jdbc.driver.OracleDriver");
                oracleDS2JNDIResource.setProperty("url", "jdbc:oracle:thin:@localhost:1521/mydbservice2");
                oracleDS2JNDIResource.setProperty("username", "db-user-name");
                oracleDS2JNDIResource.setProperty("password", "db-user-pass");
                oracleDS2JNDIResource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");
                context.getNamingResources().addResource(oracleDS2JNDIResource);

                ContextResource oracleDS3JNDIResource = new ContextResource();
                oracleDS3JNDIResource.setName("jdbc/oracleDS3");
                oracleDS3JNDIResource.setType(DataSource.class.getName());
                oracleDS3JNDIResource.setProperty("driverClassName", "oracle.jdbc.driver.OracleDriver");
                oracleDS3JNDIResource.setProperty("url", "jdbc:oracle:thin:@localhost:1521/mydbservice3");
                oracleDS3JNDIResource.setProperty("username", "db-user-name");
                oracleDS3JNDIResource.setProperty("password", "db-user-pass");
                oracleDS3JNDIResource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");
                context.getNamingResources().addResource(oracleDS3JNDIResource);                

            }
        };
    }

但是当我 运行 这个 spring 引导应用程序时,它抛出以下异常。你能帮我看看我在这里缺少什么吗?我尝试将 @Primary 添加到所有 DataSource bean。但是运气不好。

org.springframework.beans.factory.NoUniqueBeanDefinitionException:没有 'javax.sql.DataSource' 类型的合格 bean 可用:预期单个匹配 bean 但找到 3:dataSource1、dataSource2、dataSource3

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected single matching bean but found 3: dataSource1,dataSource2,dataSource3
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1041) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:345) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:340) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1092) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.init(DataSourceInitializer.java:77) ~[spring-boot-autoconfigure-1.5.9.RELEASE.jar:1.5.9.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.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:366) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:311) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:134) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    ... 38 common frames omitted

应该至少有 1 个名为 dataSource 的 bean。因此,要么用 exp dataSource1 的名称替换任何一个现有的 bean 到 dataSource,要么创建一个新的。

想说,改

@Bean(name="dataSource1", destroyMethod = "")
@Profile("dev")
@Primary
public DataSource evolutionDataSource() {
     JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
            return dataSourceLookup.getDataSource(oracleDS1);
}

@Bean(name="dataSource", destroyMethod = "")
@Profile("dev")
@Primary
public DataSource evolutionDataSource() {
    JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
            return dataSourceLookup.getDataSource(oracleDS1);
}


只需从任何现有的 dataSource* bean 中删除 @Primary。在同一个 @Profile

下最多 1 个 bean 可以有 @Primary

我能够解决这个问题。问题是,我已经在我的 spring 启动应用程序中定义了所有数据源,并且它还在导入相关的 spring 上下文文件。这意味着,我也将相同的数据源配置到我导入的 spring 上下文文件中。我从 OracleDataSourceConfiguration 中删除了所有数据源 bean(如我上面的问题中所述)并使用 TomcatEmbeddedServletContainerFactory 初始化 JNDI 数据源(引用 this),其名称与我导入的 spring 上下文文件中提到的相同.它对我有用。

 <jee:jndi-lookup id="dataSource" jndi-name="jdbc/myDataSource" />