最近在学习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); } }
结果:
原理就是使用了个回调方法,也没啥说的
这三种方式,在不显式声明使用自动注入的情况下,第一种与第二种将不会注入到自己创建的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中,而一般情况下他不会给你自动注入的;