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
到這裡就真相大白,大家可以試試打個斷點程式能不能進到該方法去。