Spring中的Aware接口
Aware接口
当我们需要用到spring中的底层的一些组件的时候,我们需要自定义bean去实现对应的Aware接口来获取底层组件,如ApplicationContextAware,BeanFactoryAware,BeanNameAware,EnvironmentAware等等
实现ApplicationContextAware接口获取ApplicationContext
package main.beans;
/**
* @author lgx
* @date 2020/12/13 13:55
* @desc
*/
public class BeanB {
private String id;
private String name;
private Integer age;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "BeanA{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", age=" + age +
'}';
}
package main.beans;
/**
* @author lgx
* @date 2020/12/13 12:21
* @desc
*/
public class BeanA{
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "BeanA{" +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
复制代码
定义BeanC去实现ApplicationContextAware接口
package main.beans;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author lgx
* @date 2020/12/13 14:16
* @desc
*/
public class BeanC implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("main.beans.BeanC.setApplicationContext 执行");
BeanA bean = applicationContext.getBean(BeanA.class);
System.out.println("获取BeanA中name属性:" + bean.getName());
}
}
复制代码
配置spring-config.xml,注册三个bean
<bean id="beanC" class="main.beans.BeanC"></bean>
<bean id="beanA" class="main.beans.BeanA">
<property name="name" value="我是BeanA"></property>
<property name="age" value="15"></property>
</bean>
<bean id="beanB" class="main.beans.BeanB">
<property name="id" value="15"></property>
<property name="name" value="我是BeanB"></property>
<property name="age" value="15"></property>
</bean>
复制代码
测试结果
package main.beans;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author lgx
* @date 2020/12/13 12:21
* @desc
*/
public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
}
}
复制代码
控制台的输出结果:
main.beans.BeanC.setApplicationContext 执行 获取BeanA中初始化方法中的属性:我是BeanA
疑问:为什么我们实现了ApplicationContextAware接口就能获取到applicationContext呢
ApplicationContextAwareProcessor
这就不得不提到ApplicationContextAwareProcessor这个类了。
ApplicationContextAwareProcessor实现了BeanPostProcessor接口,我们知道该接口可以在Bean的初始化前后去做一些操作。那么我们看看ApplicationContextAwareProcessor实现的方法中的操作
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
return bean;
}
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
复制代码
可以看到如果该bean属性EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware
,ApplicationEventPublisherAware,MessageSourceAware,ApplicationContextAware其中的一种就会走到
invokeAwareInterfaces(bean)方法中来,那么我们来看看该方法是怎么实现的:
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
// 在这里将调用自定义bean的setApplicationContext方法并传入applicationContext
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
复制代码
在方法的最后判断到bean属于ApplicationContextAware类型,将将调用自定义bean的setApplicationContext方法并传入applicationContext
到这里就真相大白,大家可以试试打个断点程序能不能进到该方法去。
作者:DQMMD
原文:Spring中的Aware接口 - 掘金