文章目录
1 ApplicationContextAwareProcessor源码解析
上篇文章《BeanPostProcessor简介》介绍了BeanPostProcessor,并对其在单实例bean创建 + 初始化过程中的运行时机做了比较详细的介绍。在上篇文章的2.3默认使用的BeanPostProcessor简单介绍那个章节里我提到针对单实例业务bean默认情况下spring注入到IOC容器中的BeanPostProcessor里有一个工作中我们可能会经常遇到的processor,就是本文要讲的ApplicationContextAwareProcessor。
其实ApplicationContextAwareProcessor的源码很简单,原理也很简单,大致如下:
其具体源码如下:
class ApplicationContextAwareProcessor implements BeanPostProcessor {
//applicationContext
private final ConfigurableApplicationContext applicationContext;
private final StringValueResolver embeddedValueResolver;
/**
* Create a new ApplicationContextAwareProcessor for the given context.
*/
public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
}
@Override
@Nullable
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((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
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(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);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
2 Aware接口简介
2.1 Aware接口源码分析+简介
通过上面的介绍,应该可以注意到一个比较重要的接口 — Aware,它其实是一个顶级接口,源码如下,非常简单。
public interface Aware {
}
在该接口上有一段注释如下:
A marker superinterface indicating that a bean is eligible to be notified by the
Spring container of a particular framework object through a callback-style method.
The actual method signature is determined by individual subinterfaces but should
typically consist of just one void-returning method that accepts a single argument.
翻译成白话就是
(1)该接口是一个标记接口
(2)如果某个bean实现了该接口,一般会有一个BeanPostProcessor类对其进行处理
(3)具体方法的定义由实现了该接口的子接口进行定义,但是通常该子接口应该只包含一个方法,且该方法的返回值为void,参数只有一个。
2.2 ApplicationContextAwareProcessor中出现的Aware
接下来我们看一下ApplicationContextAwareProcessor类中出现的各个Aware接口的源码。
- EnvironmentAware
public interface EnvironmentAware extends Aware {
/**
* Set the {@code Environment} that this component runs in.
*/
void setEnvironment(Environment environment);
}
- EmbeddedValueResolverAware
public interface EmbeddedValueResolverAware extends Aware {
/**
* Set the StringValueResolver to use for resolving embedded definition values.
*/
void setEmbeddedValueResolver(StringValueResolver resolver);
}
- ResourceLoaderAware
public interface ResourceLoaderAware extends Aware {
/**
* Set the ResourceLoader that this object runs in.
* <p>This might be a ResourcePatternResolver, which can be checked
* through {@code instanceof ResourcePatternResolver}. See also the
* {@code ResourcePatternUtils.getResourcePatternResolver} method.
* <p>Invoked after population of normal bean properties but before an init callback
* like InitializingBean's {@code afterPropertiesSet} or a custom init-method.
* Invoked before ApplicationContextAware's {@code setApplicationContext}.
* @param resourceLoader the ResourceLoader object to be used by this object
* @see org.springframework.core.io.support.ResourcePatternResolver
* @see org.springframework.core.io.support.ResourcePatternUtils#getResourcePatternResolver
*/
void setResourceLoader(ResourceLoader resourceLoader);
}
- ApplicationEventPublisherAware
public interface ApplicationEventPublisherAware extends Aware {
/**
* Set the ApplicationEventPublisher that this object runs in.
* <p>Invoked after population of normal bean properties but before an init
* callback like InitializingBean's afterPropertiesSet or a custom init-method.
* Invoked before ApplicationContextAware's setApplicationContext.
* @param applicationEventPublisher event publisher to be used by this object
*/
void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher);
}
- MessageSourceAware
public interface MessageSourceAware extends Aware {
/**
* Set the MessageSource that this object runs in.
* <p>Invoked after population of normal bean properties but before an init
* callback like InitializingBean's afterPropertiesSet or a custom init-method.
* Invoked before ApplicationContextAware's setApplicationContext.
* @param messageSource message source to be used by this object
*/
void setMessageSource(MessageSource messageSource);
}
- ApplicationContextAware
public interface ApplicationContextAware extends Aware {
/**
* Set the ApplicationContext that this object runs in.
* Normally this call will be used to initialize the object.
* <p>Invoked after population of normal bean properties but before an init callback such
* as {@link org.springframework.beans.factory.InitializingBean#afterPropertiesSet()}
* or a custom init-method. Invoked after {@link ResourceLoaderAware#setResourceLoader},
* {@link ApplicationEventPublisherAware#setApplicationEventPublisher} and
* {@link MessageSourceAware}, if applicable.
* @param applicationContext the ApplicationContext object to be used by this object
* @throws ApplicationContextException in case of context initialization errors
* @throws BeansException if thrown by application context methods
* @see org.springframework.beans.factory.BeanInitializationException
*/
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
可以看到各个Aware都满足于只包含一个方法,且该方法的返回值为void,参数只有一个
的要求。
限于篇幅,将在下篇博客里玩一下上面几个Aware。