1. 背景介绍
在上一篇文章【Spring Cooking】厨师就位(二)AnnotatedBeanDefinitionReader注册配置类 中,介绍了 AnnotatedBeanDefinitionReader 是如何注册配置类的 BeanDefinition 。此时整个容器依然还处于就绪阶段,厨师还在途中。本篇文章继续沿着注解开发的入口,开始探索十分重要的 refresh() 方法。
其中
postProcessBeanFactory(beanFactory)
onRefresh()
是空方法,留给子类去覆写。对于 AnnotationConfigApplicationContext,对于上述两个方法都没有覆写。
本篇着重讲解 refresh() 中的 prepareBeanFactory()
。见名知其意,准备 BeanFactory,那是谁去准备这个 BeanFactory呢?其实就是 ApplicationContext。此方法主要就是配置 factory 的标准 context 特性,像 context class loader 和 post processor
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
}
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
contextRefresh.end();
}
}
}
}
2. 学习目标
- 了解 prepareBeanFactory() 做了什么工作
- 了解每个注册组件的功能
3. 关键问题
4. 源码追踪
prepareBeanFactory()
-
beanFactory.setBeanClassLoader(getClassLoader())
配置 beanFactory 的类加载器,此类加载器从 ApplicationContext 获取 -
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()))
配置Spring EL表达式解释器 StandardBeanExpressionResolver,主要用于解析spel表达式(#{}),注意与环境变量占位符区分(${})关于 StandardBeanExpressionResolver 如何去解析 spel 表达式,可参考另一篇文章 【SpringCooking】Spring组件库之StandardBeanExpressionResolver
-
beanFactory.addPropertyEditorRegistrar()
配置 PropertyEditorRegistrar,用于注册 PropertyEditor,关于 PropertyEditor 参照另一篇文章 【SpringCooking】Spring组件库之PropertyEditor -
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this))
添加 BeanPostProcessor - ApplicationContextAwareProcessor,这是一个很重要的 BeanPostProcessor,为实现了xxx_Aware接口的 Bean 注入各种上下文对象 -
beanFactory.ignoreDependencyInterface()
忽略 Aware 接口的依赖,也就是某个类自动注入 xxx_Aware 时不会起作用。这与上一步对应起来,就是只能通过 ApplicationContextAwareProcessor 去处理 Aware 接口的依赖 -
beanFactory.registerResolvableDependency(Class<?> dependencyType, @Nullable Object autowiredValue)
注册特定依赖类型的自动注入值,简单来说就是,当需要注入 dependencyType 时,会以 autowiredValue 来注入。这里注册了四种特定依赖类型的自动注入值- BeanFactory.class, beanFactory
- ResourceLoader.class, this
- ApplicationEventPublisher.class, this
- ApplicationContext.class, this
其中 beanFactory 为 DefaultListableBeanFactory,this 为 AnnotationConfigApplicationContext
当我们需要依赖上述四种类型时,可以直接注入
@Autowired private ApplicationContext context; @Autowired private BeanFactory beanFactory; @Autowired private ApplicationEventPublisher publisher; @Autowired private ResourceLoader resourceLoader;
-
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this))
添加 BeanPostProcessor - ApplicationListenerDetector,检测实现了 ApplicationListener 的 bean 。它可以捕获到到 getBeanNamesForType 无法检测到的bean以及仅针对顶级bean工作的相关操作 -
beanFactory.registerSingleton()
注册了四个 bean,分别是systemProperties - 系统属性变量
systemEnvironment - 系统环境变量
environment - 包含前两者
applicationStartup
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
if (!shouldIgnoreSpel) {
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}
}
ApplicationContextAwareProcessor
主要处理实现了 xxx_Aware 接口的 Bean,调用 setter 方法注入对应依赖
class ApplicationContextAwareProcessor implements BeanPostProcessor {
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(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 ||
bean instanceof ApplicationStartupAware)) {
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;
}
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);
}
if (bean instanceof ApplicationStartupAware) {
((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
EmbeddedValueResolver
用于处理占位符和表达式
public class EmbeddedValueResolver implements StringValueResolver {
private final BeanExpressionContext exprContext;
@Nullable
private final BeanExpressionResolver exprResolver;
public EmbeddedValueResolver(ConfigurableBeanFactory beanFactory) {
this.exprContext = new BeanExpressionContext(beanFactory, null);
this.exprResolver = beanFactory.getBeanExpressionResolver();
}
}
ApplicationListenerDetector
BeanPostProcessor that detects beans which implement the ApplicationListener interface. This catches beans that can’t reliably be detected by getBeanNamesForType and related operations which only work against top-level beans.
With standard Java serialization, this post-processor won’t get serialized as part of DisposableBeanAdapter to begin with. However, with alternative serialization mechanisms, DisposableBeanAdapter.writeReplace might not get used at all, so we defensively mark this post-processor’s field state as transient.
这是一个 BeanPostProcessor ,同于检测实现 ApplicationListener 接口的 bean,并将其添加到 ApplicationContext,实际是往 ApplicationContext 的 applicationEventMulticaster 添加 ApplicationListener
applicationEventMulticaster 会在 refresh() 方法的 initApplicationEventMulticaster() 进行初始化,ApplicationListener 会在 refresh() 方法的 registerListener() 进行注册,具体可参考 【SpringCooking】厨师就位(六)refresh方法之initApplicationEventMulticaster()
class ApplicationListenerDetector implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor {
private static final Log logger = LogFactory.getLog(ApplicationListenerDetector.class);
private final transient AbstractApplicationContext applicationContext;
private final transient Map<String, Boolean> singletonNames = new ConcurrentHashMap<>(256);
public ApplicationListenerDetector(AbstractApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if (ApplicationListener.class.isAssignableFrom(beanType)) {
this.singletonNames.put(beanName, beanDefinition.isSingleton());
}
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof ApplicationListener) {
// potentially not detected as a listener by getBeanNamesForType retrieval
Boolean flag = this.singletonNames.get(beanName);
if (Boolean.TRUE.equals(flag)) {
// singleton bean (top-level or inner): register on the fly
this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
}
else if (Boolean.FALSE.equals(flag)) {
if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
// inner bean with other scope - can't reliably process events
logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
"but is not reachable for event multicasting by its containing ApplicationContext " +
"because it does not have singleton scope. Only top-level listener beans are allowed " +
"to be of non-singleton scope.");
}
this.singletonNames.remove(beanName);
}
}
return bean;
}
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) {
if (bean instanceof ApplicationListener) {
try {
ApplicationEventMulticaster multicaster = this.applicationContext.getApplicationEventMulticaster();
multicaster.removeApplicationListener((ApplicationListener<?>) bean);
multicaster.removeApplicationListenerBean(beanName);
}
catch (IllegalStateException ex) {
// ApplicationEventMulticaster not initialized yet - no need to remove a listener
}
}
}
@Override
public boolean requiresDestruction(Object bean) {
return (bean instanceof ApplicationListener);
}
@Override
public boolean equals(@Nullable Object other) {
return (this == other || (other instanceof ApplicationListenerDetector &&
this.applicationContext == ((ApplicationListenerDetector) other).applicationContext));
}
@Override
public int hashCode() {
return ObjectUtils.nullSafeHashCode(this.applicationContext);
}
}
5. 结论
-
了解 prepareBeanFactory() 做了什么工作
跑完 prepareBeanFactory(),beanFactory 以下属性发生了变化
beanClassLoader - 配置 classloader
beanExpressionResolver - 配置 Spring EL表达式解析器
propertyEditorRegistrars - 配置 propertyEditor 注册器
ignoredDependencyInterfaces - 配置忽略的依赖接口,即注入这些接口时将被无视
resolvableDependencies - 配置特定依赖类型的自动注入值,即注入这些接口时将直接注入给定的值
beanPostProcessors - 添加两个 BeanPostProcessor
manualSingletonNames - LinkedHashSet结构,储存手动注册组件的 beanName
singletonObjects - ConcurrentHashMap结构,存储已注册的 beanName 和 bean实例
registeredSingletons - LinkedHashSet结构,存储已注册的 beanName -
了解每个注册组件的功能
StandardBeanExpressionResolver - 处理spel表达式
PropertyEditorRegistrar - 注册 PropertyEditor
ApplicationContextAwareProcessor - 为实现 xxxAware 接口的 bean 注入 xxx 依赖
ApplicationListenerDetector - 检测实现了 ApplicationListener 的 bean
6. 注意细节
7. 待研究
-
ApplicationListenerDetector, ApplicationListener, ApplicationEventMulticaster 三者的关系
-
在 ApplicationListenerDetector 的注释中说到,它能捕获到一些 Bean,这些 Bean 如果用仅针对 top-level bean 方法不能可靠地检测出来,如 getBeanNamesForType() 或者相关的操作。
This catches beans that can’t reliably be detected by getBeanNamesForType and related operations which only work against top-level beans.
查看 getBeanNamesForType() 方法,其在 ListableBeanFactory 接口下
public interface ListableBeanFactory extends BeanFactory { String[] getBeanNamesForType(ResolvableType type); String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit); String[] getBeanNamesForType(@Nullable Class<?> type); String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit); <T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException; <T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException; }
这些方法的注释都有一句加粗的NOTE
NOTE: This method introspects top-level beans only. It does not check nested beans which might match the specified type as well.
因此有必要了解 top-level beans 和 nested beans 是什么?是类与内部类的关系吗?
这种不能检测的场景是什么?