首页 > 代码库 > Sping Environment为Null的原因和解决方法

Sping Environment为Null的原因和解决方法

参考:https://github.com/spring-projects/spring-boot/issues/4711 这个issue提出不到20天给我搜出来了,还是相信google的强大

问题: 
在spring的Configuration使用@Bean注册一个BeanFactoryPostProcessor Bean,发现使用@PropertySource,并注入@Resource private Environment env;发现env为null.我调试的大概一个过程,BeanFactoryPostProcessor Bean创建得比较早,创建它之前先创建它的依赖Bean Configuration,而这时发现创建的Configuration的env就是null了.深入的就没去追究了!

解决: 
让此Configuration类实现EnvironmentAware接口,这个接口只有一个void setEnvironment(Environment environment);方法.这里的回调能得到Environment,问题解决!

修改前的代码:

package org.exam.config;import org.exam.service.TestBeanFactoryPostProcessor;import org.exam.service.UserServiceImpl;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.PropertySource;import org.springframework.core.env.Environment;import javax.annotation.Resource;@Configuration@ComponentScan(basePackages = {"org.exam.service"})@PropertySource("classpath:config.properties")public class AppConfigOld {    @Resource    private Environment env;    @Bean    public UserServiceImpl userService(){        System.out.println(env);        return new UserServiceImpl();    }    /*    未加入这个BeanFactoryPostProcessor一切都很正常,一旦加入这个@Bean,env就变为null    @Bean    public TestBeanFactoryPostProcessor testBeanFactoryPostProcessor(){        System.out.println(env);        return new TestBeanFactoryPostProcessor();    }    */}

修改后的代码:

package org.exam.config;import org.exam.service.TestBeanFactoryPostProcessor;import org.exam.service.UserServiceImpl;import org.springframework.context.EnvironmentAware;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.PropertySource;import org.springframework.core.env.Environment;@Configuration@ComponentScan(basePackages = {"org.exam.service"})@PropertySource("classpath:config.properties")public class AppConfig implements EnvironmentAware {    private Environment env;    @Override    public void setEnvironment(Environment environment) {        this.env=environment;    }    @Bean    public UserServiceImpl userService(){        System.out.println(env);        return new UserServiceImpl();    }    @Bean    public TestBeanFactoryPostProcessor testBeanFactoryPostProcessor(){        System.out.println(env);        return new TestBeanFactoryPostProcessor();    }}

值得一提的是:wilkinsona的回答是不建议使用ApplicationContext.虽然可以从ApplicationContext得到Environment,但是这样会在BeanFactoryPostProcessor的创建过程中会引起application context的所有依赖Bean都创建过早,这不是期望的一个结果.

参考:https://github.com/spring-projects/spring-boot/issues/4711 这个issue提出不到20天给我搜出来了,还是相信google的强大

问题: 
在spring的Configuration使用@Bean注册一个BeanFactoryPostProcessor Bean,发现使用@PropertySource,并注入@Resource private Environment env;发现env为null.我调试的大概一个过程,BeanFactoryPostProcessor Bean创建得比较早,创建它之前先创建它的依赖Bean Configuration,而这时发现创建的Configuration的env就是null了.深入的就没去追究了!

解决: 
让此Configuration类实现EnvironmentAware接口,这个接口只有一个void setEnvironment(Environment environment);方法.这里的回调能得到Environment,问题解决!

修改前的代码:

package org.exam.config;import org.exam.service.TestBeanFactoryPostProcessor;import org.exam.service.UserServiceImpl;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.PropertySource;import org.springframework.core.env.Environment;import javax.annotation.Resource;@Configuration@ComponentScan(basePackages = {"org.exam.service"})@PropertySource("classpath:config.properties")public class AppConfigOld {    @Resource    private Environment env;    @Bean    public UserServiceImpl userService(){        System.out.println(env);        return new UserServiceImpl();    }    /*    未加入这个BeanFactoryPostProcessor一切都很正常,一旦加入这个@Bean,env就变为null    @Bean    public TestBeanFactoryPostProcessor testBeanFactoryPostProcessor(){        System.out.println(env);        return new TestBeanFactoryPostProcessor();    }    */}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

修改后的代码:

package org.exam.config;import org.exam.service.TestBeanFactoryPostProcessor;import org.exam.service.UserServiceImpl;import org.springframework.context.EnvironmentAware;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.PropertySource;import org.springframework.core.env.Environment;@Configuration@ComponentScan(basePackages = {"org.exam.service"})@PropertySource("classpath:config.properties")public class AppConfig implements EnvironmentAware {    private Environment env;    @Override    public void setEnvironment(Environment environment) {        this.env=environment;    }    @Bean    public UserServiceImpl userService(){        System.out.println(env);        return new UserServiceImpl();    }    @Bean    public TestBeanFactoryPostProcessor testBeanFactoryPostProcessor(){        System.out.println(env);        return new TestBeanFactoryPostProcessor();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

值得一提的是:wilkinsona的回答是不建议使用ApplicationContext.虽然可以从ApplicationContext得到Environment,但是这样会在BeanFactoryPostProcessor的创建过程中会引起application context的所有依赖Bean都创建过早,这不是期望的一个结果.

Sping Environment为Null的原因和解决方法