首页 > 代码库 > 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的原因和解决方法