一、简介
Bean对象实现各种Aware接口,Spring就可以在合适的时机调用,感知特定的信息
- 例如让Bean感知到BeanFactory,BeanName,ApplicationContext
二、实现Aware
2.1 定义Aware接口
- 标记类接口,实现该接口可以被Spring容器感知
public interface Aware {
}
2.2 定义感知类
提供四个子接口,感知不同类型的信息
BeanNameAware,感知BeanName
public interface BeanNameAware extends Aware{
void setBeanName(String name);
}
BeanFactoryAware,感知BeanFactory
public interface BeanFactoryAware extends Aware{
void setBeanFactory(BeanFactory beanFactory);
}
BeanClassLoaderAware,感知ClassLoader
public interface BeanClassLoaderAware extends Aware{
void setBeanClassLoader(ClassLoader classLoader);
}
ApplicationContextAware,感知ApplicationContext
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext);
}
2.3 spring感知Aware的位置
修改AbstractAutowireCapableBeanFactory
类的initializeBean
方法
- 根据Bean实现的Aware接口,传入对应的属性
protected Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) {
// invokeAwareMethods
if (bean instanceof Aware) {
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(this);
}
if (bean instanceof BeanClassLoaderAware){
((BeanClassLoaderAware) bean).setBeanClassLoader(ClassUtil.getClassLoader());
}
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
}
······
}
2.4 特殊处理ApplicationContextAware
为什么要特殊处理?
- 因为BeanFactory是ApplicationContext的一个属性,BeanFactory创建Bean的时候,无法拿到ApplicationContext,所以我们需要通过某种方式,将ApplicationContext传递给BeanFactory
如何实现?
- 目前我们只有两种方式,BeanFactoryPostProcessor和BeanPostProcessor,由于BeanFactoryPostProcessor本质是通过PropertyValues传递,这样就会强制Bean必须有一个叫做ApplicationContext的属性,这样就不太灵活。因此使用BeanPostProcessor来传递,只需在初始化前方法设置Application属性即可。
新建一个ApplicationContextAwareProcessor
- 在其中提供一个ApplicationContext属性,在实例化的时候就传入值
public class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ApplicationContext applicationContext;
public ApplicationContextAwareProcessor(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(applicationContext);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
在refresh方法重建BeanFactory的时候,传递ApplicationContext
@Override
public void refresh() {
// 1. 创建 BeanFactory,并加载 BeanDefinition
refreshBeanFactory();
// 2. 获取 BeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 3. 需要特殊处理的Aware,通过BeanPostProcessor传递ApplicationContext
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 4. 在Bean实例化之前,执行 BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// 5. BeanPostProcessor需要提前于其他Bean对象实例化之前执行注册操作
registerBeanPostProcessors(beanFactory);
// 6. 提前实例化单例Bean对象,主动触发getBean
beanFactory.preInstantiateSingletons();
}
同样在initializeBean()方法,会自动调用applyBeanPostProcessorsBeforeInitialization(),注入ApplicationContext
protected Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) {
······
//执行BeanPostProcessor的前置处理(初始化前)
Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
······
}
三、测试
让Person实现四个Aware接口
@Slf4j
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class Person implements BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware {
private String name;
private int age;
private Cat cat;
private ApplicationContext applicationContext;
private BeanFactory beanFactory;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
log.info("ClassLoader:" + classLoader);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
public void setBeanName(String name) {
log.info("Bean Name is:" + name);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
}
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="cat" class="cn.shopifymall.springframework.test.bean.Cat">
<property name="name" value="tomcat"/>
<property name="weight" value="2000"/>
</bean>
<bean id="person" class="cn.shopifymall.springframework.test.bean.Person">
<property name="name" value="LeBron James"/>
<property name="age" value="18"/>
<property name="cat" ref="cat"/>
</bean>
</beans>
测试类
public class ApiTest {
@Test
public void test_aware() {
// 1.初始化 BeanFactory
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
// 2. 获取Bean对象调用方法
Person person = (Person) applicationContext.getBean("person");
System.out.println("测试结果:" + person);
}
}
控制台打印
- ClassLoader
- BeanName
16:19:07.323 [main] INFO cn.shopifymall.springframework.test.bean.Person - ClassLoader:sun.misc.Launcher$AppClassLoader@18b4aac2
16:19:07.325 [main] INFO cn.shopifymall.springframework.test.bean.Person - Bean Name is:person
Debugger效果
- ApplicationContext
- BeanFactory
至此,四个Aware,都完成了注入