【问题标题】:Spring Profiles org.springframework.beans.factory.NoSuchBeanDefinitionExceptionSpring Profiles org.springframework.beans.factory.NoSuchBeanDefinitionException
【发布时间】:2017-07-08 14:35:15
【问题描述】:

我的示例项目是基于 Maven 的结构,我的所有应用程序属性文件都在 src/main/resources 文件夹下。下面是完整的示例代码。我不明白为什么我的代码无法正确找到配置文件,除非我使用 @PropertySource 注释。

我的实际疑问是: 我在 application.properties 文件中配置了很好的 spring 属性,但是为什么它找不到配置文件及其各自的属性文件?除非我使用@PropertySource 注释,否则我不会获得 env.getProperty("mysql.url") 的值。我的意思是 Environment 类无法从配置文件属性文件中获取值。 为什么?

我收到如下错误:

Jul 08, 2017 7:54:26 PM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@300ffa5d: startup date [Sat Jul 08 19:54:26 IST 2017]; root of context hierarchy
helloBean
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'datasource' available
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1207)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1084)
    at com.oreilly.datasource.Main2.main(Main2.java:15)

DatasourceConfig.java

package com.oreilly.datasource;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
import org.springframework.core.env.Environment;

@Configuration
/*@PropertySource("classpath:/application.properties")
@PropertySource("classpath:/dev/application-dev.properties")
@PropertySource("classpath:/prod/application-prod.properties")*/
public class DatasourceConfig {

    @Autowired
    private Environment env;

    @Bean(name="helloBean")
    public String helloWorld() {
        System.out.println("helloBean");
        return "helloWorld....";
    }

    @Bean(name="datasource")
    @Profile("dev")
    public DataSource datasourceForDev(){
        BasicDataSource dataSource = new BasicDataSource();
        System.out.println(env.getProperty("mysql.url"));
        return dataSource;
    }

    @Bean(name="datasource")
    @Profile("prod")
    public DataSource datasourceForProd(){
        BasicDataSource dataSource = new BasicDataSource();
        System.out.println(env.getProperty("mysql.url"));
        return dataSource;
    }
}

Main2.java

package com.oreilly.datasource;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main2 {


    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DatasourceConfig.class);

        DataSource dataSource = context.getBean("datasource", DataSource.class);
        String helloBean = context.getBean("helloBean", String.class);


    }

}

application.properties

spring.profiles.active=prod
spring.config.name=application
spring.config.location=classpath:/application.properties,classpath:/dev/application-dev.properties,classpath:/prod/application-dev.properties

项目文件夹结构如下:

请告诉我出了什么问题?

【问题讨论】:

    标签: java spring maven spring-mvc spring-profiles


    【解决方案1】:

    Spring 很聪明,它根据 application.properties 中分配给 spring.profiles.active 的值选择 application-x.properties(其中 x 是环境),因此您不必担心注册所有不同@PropertySource 注释中的文件。

    您可以在此处获取更多信息:https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-profile-specific-properties

    我建议你删除所有的@Profile 注释,只保留一个可变的数据源(取决于 application.properties 中选择的环境)。通过我在本文末尾的示例,您可能会理解这一点。

    如果你想为一个特定的配置文件(比如说dev)定义一个mysql.url,你需要在application-dev.properties文件中添加“mysql.url”,然后设置spring.profiles.active在 application.properties 中对 dev 的值。

    然后,在您的 DatasourceConfig.java 中,您可以执行以下操作:

    @Autowired
    private Environment env;
    
    //Takes the mysqlUrl from application-x.properties (where x is the value of spring.profiles.active that comes from application.properties)
    @Value("${mysql.url}")
    private String mysqlUrl;
    
    @Bean(name="helloBean")...
    
    @Bean(name="datasource")
    public DataSource datasource() {
        BasicDataSource dataSource = new BasicDataSource();
        System.out.println(mySqlUrl); //This value is variable depending of the profile that you're pointing on.
        return dataSource;
    }
    

    请告诉我这对你有用。

    【讨论】:

    • 附加说明:您需要在资源根目录中定义您的 application.properties 和 application-x.properties 文件,以便 Spring 自动检测它们。
    • 我认为你应该正确理解我的查询。我们应该使用 Environment 类而不是像“mysql.url”这样声明每个属性变量...我保留了@Profile 注释来声明 2 个配置文件(开发和 prod) 使用 2 种方法..
    【解决方案2】:

    我已经通过如下修改解决了我的问题:

    @PropertySource("classpath:/${spring.profiles.active}/application-${spring.profiles.active}.properties")
    

    现在我可以动态获取 application-dev.properties(或)application-prod.properties。

    注意Environment 类需要 @PropertySource 注解,否则 env.get('someproperty') 会得到 null。

    【讨论】:

      【解决方案3】:
      @Configuration
      @PropertySource("classpath:application.properties")
      public class DatasourceConfig {
      ....
      }
      

      将属性文件放在与 application.property 相同的位置,并遵循命名约定 application-{profile}.properties,如 application-dev.properties、application-prod.properties。


      '我希望根据我在 application.properties 中声明的配置文件自动获取属性文件。'

      使用 -Dspring.profiles.active=dev/prod 运行您的应用程序。弹簧加载 1)application.property,2)pplication-dev/prod.properties 文件,覆盖 application.property 中的值

      【讨论】:

      • 我希望根据我在 application.properties 中声明的配置文件自动获取属性文件。有什么想法吗?
      • 不使用@PropertySource 应该可以工作,如何?我的意思是它应该自动获取我的 application-dev.properties,如何?
      猜你喜欢
      • 1970-01-01
      • 2013-04-19
      • 2014-04-16
      • 1970-01-01
      • 1970-01-01
      • 2015-01-19
      • 1970-01-01
      • 2020-03-30
      • 1970-01-01
      相关资源
      最近更新 更多