这个是spring-beans包中的概念,正常情况下我们使用bean是不需要考虑容器相关的特性的,所以基本在项目中不会接触这个接口,但是这个接口是获取容器相关属性的核心,比如自己定一个一个bean,然后想在这个bean中获取applicationContext或者beanName等属性,那么我们就需要了解Aware接口相关的特性了。我先说下源码中如何获取spring容器相关特性,然后再举个例子说明下。
1.spring容器启动时会调用AbstractApplicationContext类的prepareBeanFactory方法,其中会定义bean的后置处理器ApplicationContextAwareProcessor
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.setBeanClassLoader(this.getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
if (beanFactory.containsBean("loadTimeWeaver")) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
if (!beanFactory.containsLocalBean("environment")) {
beanFactory.registerSingleton("environment", this.getEnvironment());
}
if (!beanFactory.containsLocalBean("systemProperties")) {
beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean("systemEnvironment")) {
beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment());
}
2.bean在初始化前会调用一次ApplicationContextAwareProcessor类的postProcessBeforeInitialization方法
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
if (System.getSecurityManager() != null && (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
ApplicationContextAwareProcessor.this.invokeAwareInterfaces(bean);
return null;
}
}, acc);
} else {
this.invokeAwareInterfaces(bean);
}
return bean;
}
3.注意postProcessBeforeInitialization方法中具体的invoke方法,如果实现Aware接口会继续判断实现了具体的什么接口,执行对应接口的方法。
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(new ApplicationContextAwareProcessor.EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
}
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);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
}
}
}
举个例子,MyApplicationContextAware实现了ApplicationContextAware接口,那么在初始化前会调用setApplicationContext方法,则可以拿到ApplicationContext
@Service
public class MyApplicationContextAware implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public ApplicationContext getApplicationContext(){
return applicationContext;
}
}
再举个例子,可以拿到对应bean的beanName
@Component
public class MyBeanNameAware implements BeanNameAware {
private BeanName beanName;
@Override
public void setBeanName(BeanName beanName) throws BeansException {
this.beanName = beanName;
}
public BeanName getBeanName(){
return beanName;
}
}
网友评论