关于spring中environment注入为null的一点理解

时间:2024-03-19 20:41:38

最近在学习spring的源码 ,在学习中经常出现一件事,就是自动注入的某些属性不知道忘了那些配置经常会出现null的现象,现在做一些统一整理:

首先:spring中的bean从注入方式上会分成三种,一种是普通的javaBean,就是自己在配置文件中写好的放在容器中的,在一种就是系统环境bean,包括三个,Environment,SystemPropertits,SystemEnvironment,还有一种是实现了XXXAware接口的bean,

第一种不解释

第二种,这种bean不是我们自己创建的,而是spring帮我们自动创建的,spring代码如下:

        // Register default environment beans.
        if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
        }

儿上面的getEnvironment()方法的代码如下:

public ConfigurableEnvironment getEnvironment() {
   if (this.environment == null) {
      this.environment = createEnvironment();
   }
   return this.environment;
}
protected ConfigurableEnvironment createEnvironment() {
   return new StandardEnvironment();
}

默认会返回一个Environment接口的实现StandardEnvironment;用来存贮我们所需要的属性;

第三种,实现XXXAware接口的类

代码如下:

private void invokeAwareMethods(String beanName, Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware)bean).setBeanName(beanName);
        }

        if (bean instanceof BeanClassLoaderAware) {
            ((BeanClassLoaderAware)bean).setBeanClassLoader(this.getBeanClassLoader());
        }

        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware)bean).setBeanFactory(this);
        }
    }

}

這是系統默认的几个Aware,其他的Aware实现与之类似,具体使用方法如下:

public class Student  implements EnvironmentAware {
    Environment environment;

    private int id;
    public Student(int id) {
        this.id=id;
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment=environment;
    }
}

测试代码

public class Main {

    public static void main (String[] args){
        ApplicationContext context=new ClassPathXmlApplicationContext("classpath:resources\\META-INF\\spring\\camel-context.xml");
        System.out.println(((Student)context.getBean("xiaoming")).environment==null);
        
    }
}

结果:

关于spring中environment注入为null的一点理解

原理就是使用了个回调方法,也没啥说的

这三种方式,在不显式声明使用自动注入的情况下,第一种与第二种将不会注入到自己创建的javaBean之中,在开启自动注入的情况下,也就是说在配置文件中添加

component-scan

子元素,前两种的属性将会注入到所创建的javaBean之中;

总结,当所创建的javaBean之中属性出现null时,考虑如下解决方式:

1.仔细查看配置文件与配置类,是否声明了相关的类型,且

constructor-arg 
property 等配置文件的相关子元素是否配置得当

IDEA编译器为spring提供了相当强的插件支持,建议换个编译器~~~~

2.若是属性在配置文件或者配置类里面已经声明且符合唯一约束;

3.若是使用了@Autowire等相关注解,查看是否开启了自动注解,开启自动注解方法是;在相关的配置文件或者配置类里面声明

<context:component-scan/>

或者是

@ComponentScan 注解

4。此时会解决绝大部分null问题,当仍为null,考虑实现相关的Aware接口,比如ApplicationContextAware,此时他会将ApplicationContext注入到你的javaBean中,而一般情况下他不会给你自动注入的;