Spring注解驱动开发学习总结9:自动装配注入Spring底层组件&原理解析
1、自动装配注入Spring底层组件
自定义bean如果想要使用Spring容器底层的一些组件,比如ApplicationContext, BeanFactory等,可以让类实现xxxAware接口。Spring在创建对象的时候,会调用接口规定的方法注入组件xxx。
1、查看Aware接口。
package org.springframework.beans.factory;
public interface Aware {
}
2、Aware有很多子接口,以下仅框出了ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware。
1.1 构建Blue类
构建Blue类:com/example/bean/Blue.java。
让Blue类实现:ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware接口:
1)setApplicationContext方法:将IOC容器赋值给Blue类;
2)setBeanName方法:打印当前bean的名称;
3)setEmbeddedValueResolver方法:对字符串进行解析
package com.example.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.util.StringValueResolver;
public class Blue implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {
ApplicationContext applicationContext = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("applicationContext: " + applicationContext);
this.applicationContext = applicationContext;
}
@Override
public void setBeanName(String name) {
System.out.println("beanName: " + name);
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
String s = resolver.resolveStringValue("我的电脑的系统是:${os.name}, 我的年工资是#{20*15}k");
System.out.println("resolver: " + s);
}
}
1.2 构建配置类
构建配置类:com/example/config/MainConfigOfAware.java
在ioc容器中注入一个id为”蓝色bean“的Blue类
package com.example.config;
import com.example.bean.Blue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MainConfigOfAware {
@Bean("蓝色bean")
public Blue blue() {
return new Blue();
}
}
1.3 测试自动注入Spring底层组件
构建测试方法:testAware
@Test
public void testAware() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAware.class);
System.out.println("\nioc容器已创建完成\n");
}
运行测试方法:testAware。
可以看到自动注入的Blue类的bean中,在ioc创建完成之前,分别自动调用了xxxAware接口中的方法,从而保证Blue类可以获取到Spring底层的组件。
2、自动装配注入Spring底层组件原理
自定义bean如果想要使用Spring容器底层的一些组件,比如ApplicationContext, BeanFactory等,可以让类实现xxxAware接口就可以了。
那么这是为什么呢?
2.1 原理分析
1、在自定义的Blue类的15行打一个断点:
2:根据栈的调用关系图,此时可以看到从测试方法testAware,一直到目前的Blue 15行断点的函数调用关系。
3:中间的调用关系太多,我们直接看Blue 15行前面第2个调用函数postProcessBeforeInitialization 97行:
3.1 可以看到,Spring在bean初始化前的后置处理方法中的第97行,调用了invokeAwareInterfaces方法,也就是自动去执行Aware接口方法;
3.2 invokeAwareInterfaces方法就在第103行:
3.2.1 首先判断bean是否为Aware接口。由于Blue实现了ApplicationContextAware接口,因此肯定是Aware接口。
3.2.2 然后执行到120行,判断是否是ApplicationContextAware接口,这里也满足,因此在121行,就会将ioc容器this.applicationContext注入到我们的组件Blue中。
2.2 小结
因此可以看到,Spring容器在创建bean的过程中,在bean初始化前的后置处理方法中,会主动去回调Aware接口,如果该bean实现了xxxAware接口,那么就会调用该bean的xxxAware接口中的方法,从而将Spring底层的组件自动注入到自定义的类中。