前言
上一篇文章我们用一个demo来体验了Spring在web项目开发中的使用。并解释了Spring容器创建与初始化的位置。这一篇文章我们开始阅读代码,看看Spring容器创建、初始化的具体过程。
这篇文章里很多细枝末节并不会讲到,主要是想通过这篇文章,先了解、熟悉Spring容器的加载过程,脑子里对过程中有哪些步骤、步骤顺序等有一个全局的概念。正对一些值得深究的点,各点会有独立的文章。
背景知识
BeanFactory
比较早期的Spring Bean容器。接口中定义了作为Spring容器所要具备的方法、能力。
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
}
复制代码
ApplicationContext
对BeanFactory的扩充,实现了BeanFactory所有功能,除了此以外,还具备资源解析、事件发布、消息等功能。有多重多样的实现类。是目前主流的Spring容器。
BeanDefinition
BeanDefinition是用来描述一个Bean的,直译过来就是Bean的定义。可以看到接口定义了各种方法来描述Bean的各种属性。Spring容器在初始化Bean的时候,不是直接从配置文件到Bean的,而是从配置文件解析为BeanDefinition,然后根据BeanDefinition实例化Bean。
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
void setParentName(@Nullable String parentName);
@Nullable
String getParentName();
void setBeanClassName(@Nullable String beanClassName);
@Nullable
String getBeanClassName();
void setScope(@Nullable String scope);
@Nullable
String getScope();
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
void setDependsOn(@Nullable String... dependsOn);
@Nullable
String[] getDependsOn();
void setAutowireCandidate(boolean autowireCandidate);
boolean isAutowireCandidate();
void setPrimary(boolean primary);
boolean isPrimary();
void setFactoryBeanName(@Nullable String factoryBeanName);
@Nullable
String getFactoryBeanName();
void setFactoryMethodName(@Nullable String factoryMethodName);
@Nullable
String getFactoryMethodName();
ConstructorArgumentValues getConstructorArgumentValues();
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
MutablePropertyValues getPropertyValues();
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
void setInitMethodName(@Nullable String initMethodName);
@Nullable
String getInitMethodName();
void setDestroyMethodName(@Nullable String destroyMethodName);
@Nullable
String getDestroyMethodName();
void setRole(int role);
int getRole();
void setDescription(@Nullable String description);
@Nullable
String getDescription();
ResolvableType getResolvableType();
boolean isSingleton();
boolean isPrototype();
boolean isAbstract();
@Nullable
String getResourceDescription();
@Nullable
BeanDefinition getOriginatingBeanDefinition();
}
复制代码
BeanFactoryPostProcessor
针对BeanFactory的后置处理器。接口中只有一个方法,入参就是beanFactory。在postProcessBeanFactory()方法中可以对beanFactory进行各种修改。这是Spring对外提供的修改beanFactory的机会。实现了这个接口的类会在ApplicationContext实例化的过程中被调用,实现修改。
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
复制代码
BeanPostProcessor
针对Bean的后置处理器。这是Spring对外提供的修改已实例化bean的机会。在bean初始化前、后各有一个回调方法,默认是不做任何操作,可以实现此接口,然后做自己想要的操作。
后置处理器机制在Spring中使用非常广泛。熟知的AOP就是利用了这个机制。
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
复制代码
FactoryBean
注意啊,这里是FactoryBean。不要和上面的搞混了。顾名思义,他本质应该是一个承担了工厂角色的Bean。看接口中最核心的方法就是getObject()。你实现接口并重写这个方法,就可以自由的创建你想要的的Bean实例。在Spring容器创建Bean的时候,也是使用了一个匿名的FactoryBean。
public interface FactoryBean<T> {
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
复制代码
监听器引导初始化Spring容器
ServletContext初始化完成后,通知监听器。ContextLoaderListener进行Spring容器的初始化操作。主要逻辑在ContextLoader的initWebApplicationContext()方法完成。方法比较长,再次不做完整摘录。
获取容器类
获取容器类时,会先从servletContext中读取contextClass参数指定的类型;若无,则从ContextLoader类的defaultStrategies变量获取默认类名。
// ContextLoader类方法
protected Class<?> determineContextClass(ServletContext servletContext) {
// 从servlet上下文获取配置的contextClass
String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
if (contextClassName != null) {
try {
return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
}
catch (ClassNotFoundException ex) {
throw new ApplicationContextException("Failed to load custom context class [" + contextClassName + "]", ex);
}
}
else {
// 读取默认的context的类名
contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
try {
return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
throw new ApplicationContextException("Failed to load default context class [" + contextClassName + "]", ex);
}
}
}
复制代码
defaultStrategies的值是在ContextLoader类静态代码块中读取的。DEFAULT_STRATEGIES_PATH
对应的值为ContextLoader.properties。
// ContextLoader类静态代码块
static {
try {
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
}
catch (IOException ex) {
throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage());
}
}
复制代码
我们可以从spring-web包中找到这个ContextLoader.properties文件。其中只有一行内容,配置了Spring容器的类名。determineContextClass()方法根据类名返回对应的Class对象。
org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
复制代码
实例化容器
这一步没有特别的,就是使用BeanUtils.instantiateClass()方法,对上一步获取到的Class对象,选择默认构造函数,通过反射构造实例。最后会将类型强转为ConfigurableWebApplicationContext
。
设置父容器
然后会通过loadParentContext()方法获父容器,不过这个方法目前默认是返回null的。现在启动的其实就是Root WebApplicationContext,是没有父容器的。
注入获取配置文件位置
这里就是从servletContext获取配置文件位置,来源就是web.xml中context-parma配置的contextConfigLocation的值。
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
// 省略...
// 从servletContext获取
wac.setServletContext(sc);
String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
if (configLocationParam != null) {
wac.setConfigLocation(configLocationParam);
}
// 省略...
}
复制代码
customizeContext
这一步是,如果在web.xml配置了全局的或者上下文的初始化操作类,就会把这些类加载进来,排序并实例化,依次作用与刚创建的applicationContext。
refresh()刷新容器
这一步就是Spring容器比较关键的一步了。他会调用applicationContext的refresh方法。spring配置的读取、处理,spring bean的创建等等非常多的操作要在这一步。这一步也是需要着重学些的一步。下面会详细分析。
设置classloader
这一步是将ClassLoader与当前applicationContext以ConcurrentHashMap的显示存起来。
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
if (ccl == ContextLoader.class.getClassLoader()) {
currentContext = this.context;
}
else if (ccl != null) {
// Map<ClassLoader, WebApplicationContext> currentContextPerThread = new ConcurrentHashMap<>(1);
currentContextPerThread.put(ccl, this.context);
}
复制代码
经过上述这些操作,一个完成的applicationContext就成功创建了。Spring也就在你的程序中顺利运转起来了。
Spring容器初始化流程
前面描述了ContextLoaderListener引导创建、初始化一个Spring容器applicationContext。Spring容器想要有那些强大的功能、能力,并不是创建之后就自然拥有的,而是做了大量的准备工作,来解析、处理等等各种复杂的操作。我们接下来就看下Spring容器是如何拥有这些能力的。
refresh()定义在ConfigurableApplicationContext
接口中。
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
String ENVIRONMENT_BEAN_NAME = "environment";
String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";
String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";
String SHUTDOWN_HOOK_THREAD_NAME = "SpringContextShutdownHook";
void setId(String id);
void setParent(@Nullable ApplicationContext parent);
void setEnvironment(ConfigurableEnvironment environment);
@Override
ConfigurableEnvironment getEnvironment();
void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);
void addApplicationListener(ApplicationListener<?> listener);
void setClassLoader(ClassLoader classLoader);
void addProtocolResolver(ProtocolResolver resolver);
/**
* Load or refresh the persistent representation of the configuration, which
* might be from Java-based configuration, an XML file, a properties file, a
* relational database schema, or some other format.
* <p>As this is a startup method, it should destroy already created singletons
* if it fails, to avoid dangling resources. In other words, after invocation
* of this method, either all or no singletons at all should be instantiated.
* @throws BeansException if the bean factory could not be initialized
* @throws IllegalStateException if already initialized and multiple refresh
* attempts are not supported
*/
void refresh() throws BeansException, IllegalStateException;
void registerShutdownHook();
@Override
void close();
boolean isActive();
ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
}
复制代码
前文说过,默认的容器类是XmlWebApplicationContext,我们在这个类中搜索,发现是他的父类AbstractApplicationContext
实现了refresh()这个方法。
看到这个代码感觉非常简洁,所有步骤都封装成一个一个方法。这里是上一篇提到过的设计模式,模板方法模式。AbstractApplicationContext在refresh()方法中抽象了逻辑,规定了一些必须的步骤,同时提供方法给子类实现自己的逻辑。在保证所有子类的逻辑一致的情况下,又允许子类有不影响主逻辑的自定义逻辑。
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
// 省略...
@Override
public void refresh() throws BeansException, IllegalStateException {
// 同步处理
synchronized (this.startupShutdownMonitor) {
// 刷新前的一系列准备工作
prepareRefresh();
// 刷新并获取beanFactory,加载BeanDefinition
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// beanFactory的一些准备工作
prepareBeanFactory(beanFactory);
try {
// 允许在这里对beanFactory进行个性化修改
postProcessBeanFactory(beanFactory);
// 执行BeanFactory后置处理器,修改beanFactory
invokeBeanFactoryPostProcessors(beanFactory);
// 注册Bean后置处理器
registerBeanPostProcessors(beanFactory);
// 消息、国际化相关
initMessageSource();
// 初始化多播(multicast)相关组件
initApplicationEventMulticaster();
// 子类实现个性化逻辑
onRefresh();
// 注册ApplicationListener监听器到上面的多播(multicast)相关组件
registerListeners();
// 实例化非懒加载的单例bean
finishBeanFactoryInitialization(beanFactory);
// 刷新收尾的一系列操作
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex);
}
destroyBeans();
cancelRefresh(ex);
throw ex;
} finally {
resetCommonCaches();
}
}
}
// 省略...
}
复制代码
refresh()中各个方法大致的作用已经通过注释说明,接下来看看各个方法中具体做了什么。
prepareRefresh
这一步主要是准备工作,标志位修改啊,配置文件检查等操作,大致了解一下。
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
// 省略...
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
initPropertySources();
getEnvironment().validateRequiredProperties();
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
this.earlyApplicationEvents = new LinkedHashSet<>();
}
// 省略...
}
复制代码
obtainFreshBeanFactory
这个方法看起来很简短啊,而且顾名思义就两步:
- 刷新BeanFactory
- 获取并返回BeanFacotry
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
// 省略...
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
// 省略...
}
复制代码
但是在refreshBeanFactory()方法中,其实会做不少事情。我们仍以默认的XmlWebApplicationContext为例,通过方法搜索,可以看到父类AbstractRefreshableApplicationContext实现了这个刷新BeanFactory的方法。
从代码看出,它的逻辑就是:如果已有beanFacotry实例,就先销毁;然后新建一个beanFactory对象并初始化。
这里有几个地方注意一下:
- customizeBeanFactory():这个方法里设置beanFactory的allowCircularReferences属性,这个是用来控制是否允许循环依赖的。后面我们会讲到Spring的循环依赖,再详细讲。
- loadBeanDefinitions():这个是读取、加载bean定义Bean定义的。注意,这里只是读取BeanDefinition,还没有进行实例化。 读取的方式有很多,比如xml、扫描注解等等,也由各子类自行实现。
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
// 省略...
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 对beanFactory客制化操作
customizeBeanFactory(beanFactory);
// 读取、解析Bean的定义
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
// 省略...
}
复制代码
prepareBeanFactory
这个方法可以看到,全部是beanFactory.xxx()方法,是调整beanFactory各种设置的。
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());
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 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 (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());
}
}
// 省略...
}
复制代码
postProcessBeanFactory
这是一个空方法,由子类实现XmlWebApplicationContext的父类AbstractRefreshableWebApplicationContext实现了这个方法
简单看下
/**
* Register request/session scopes, a {@link ServletContextAwareProcessor}, etc.
*/
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
}
复制代码
invokeBeanFactoryPostProcessors
这个方法主要逻辑在PostProcessorRegistrationDelegate
类的invokeBeanFactoryPostProcessors()方法中。会寻找并执行BeanFactoryPostProcessor。具体的逻辑如下
- 入参中的后置处理器区分BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor
- 寻找实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor,排序后执行
- 寻找实现了Ordered接口的BeanDefinitionRegistryPostProcessor,排序后执行
- 寻找剩下的BeanDefinitionRegistryPostProcessor,排序后执行
- 获取所有后置处理器,然后分类:已执行的、优先执行的、有序执行的、未排序的
- 排序并执行优先执行的(实现了PriorityOrdered接口的)BeanFactoryPostProcessor
- 排序并执行排序的(实现了Ordered接口的)BeanFactoryPostProcessor
- 执行剩余的BeanFactoryPostProcessor
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 这里区分BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor
// 因为执行的顺序不一样
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 1. 寻找实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor,排序后执行
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 2. 寻找实现了Ordered接口的BeanDefinitionRegistryPostProcessor,排序后执行
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// 3. 寻找剩下的BeanDefinitionRegistryPostProcessor,排序后执行
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// 执行剩余的BeanDefinitionRegistryPostProcessor
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 执行入参带入的BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// 执行入参带入的后置处理器
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 获取所有后置处理器
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
// 这里将所有后置处理器分类:已执行的、优先执行的、有序执行的、未排序的
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 排序并执行优先执行的(实现了PriorityOrdered接口的)BeanFactoryPostProcessor
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 排序并执行排序的(实现了Ordered接口的)BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// 执行剩余的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
beanFactory.clearMetadataCache();
}
复制代码
registerBeanPostProcessors
这个方法顾名思义就是注册BeanPostProcessor。主要逻辑是在PostProcessorRegistrationDelegate
类的registerBeanPostProcessors()
方法中。逻辑如下:
- 获取并实例化所有BeanPostProcessor
- 按PriorityOrdered、Ordered、其他 区分
- 排序并注册实现了PriorityOrdered的BeanPostProcessor
- 排序并注册实现了Ordered的BeanPostProcessor
- 注册剩余BeanPostProcessor
- 排序并注册MergedBeanDefinitionPostProcessor
- 注册ApplicationListenerDetector(事件监听器的后置处理器)
public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// 获取所有BeanPostProcessor名称
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
// 实例化BeanPostProcessor
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// 按PriorityOrdered、Ordered、其他 区分
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 1. 排序并注册实现了PriorityOrdered的BeanPostProcessor
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// 2. 排序并注册实现了Ordered的BeanPostProcessor
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// 3. 注册剩余BeanPostProcessor
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// 4. 排序注册MergedBeanDefinitionPostProcessor。这个可能有注册过的再次注册
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// 注册ApplicationListenerDetector(事件监听器的后置处理器),保持在处理器链最后
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
复制代码
initMessageSource
消息、国际化相关,暂时先略过不讲。= =
initApplicationEventMulticaster
这里主要是实例化一个applicationEventMulticaster,application事件多播器(= =是这样翻译么)。用来支持ApplicationContext实现的ApplicationEventPublisher
接口的事件发布功能。暂时先略过不讲。= =
onRefresh
空方法,子类实现个性化逻辑,暂时先略过不讲。= =
registerListeners
这个方法就是在applicationEventMulticaster(前面刚提到的)上注册事件监听器。简单看下。
插句题外话,观察到一个现象,很多方法都是先处理ApplicationContext中的成员变量,然后再分局类型获取创建实例,再对获取到的实例分类处理。看invokeBeanFactoryPostProcessors()、registerBeanPostProcessors()还有当前这一段代码,都有这个特点。那么联想到,我们其实是可以对ApplicationContext中的内容自定义修改然后refresh()的。= =
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
// 省略...
protected void registerListeners() {
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
// 省略...
}
复制代码
finishBeanFactoryInitialization
这里可以说是Spring容器初始化最重要的一步。在这一步中,会把所有非懒加载的单例对象都实例化,交给容器管理。这一块的内容可能比较多。这里先简单说一下Bean实例化步骤,以后写一篇文章详谈。
- 实例化
- 属性填充
- BeanNameAware、BeanFactoryAware、ApplicationContextAware
- BeanPostProcessor.postProcessBeforeInitialization
- @PostConstruct
- InitializationBean
- init-method
- BeanPostProcessor.postProcessAfterInitialization
finishRefresh
主要是refresh收尾的操作。暂时先略过不讲。= =
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
// 省略...
protected void finishRefresh() {
clearResourceCaches();
initLifecycleProcessor();
getLifecycleProcessor().onRefresh();
publishEvent(new ContextRefreshedEvent(this));
LiveBeansView.registerApplicationContext(this);
}
// 省略...
}
复制代码
结语
这一篇文章写的非常的长了,用一张图来总结一下吧。本文只是对ContextLoaderListener引导初始化Spring容器的流程做了了一些梳理,希望自己对这个过程熟悉,特别是refresh()方法,然后再深入看流程中的重要步骤。