參考: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都創建過早,這不是期望的一個結果.
