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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM