参考: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都创建过早,这不是期望的一个结果.

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐