上一篇Spring源码十二:事件发布源码跟踪中,我们介绍了Spring中是如何使用观察者设计模式的思想来实现事件驱动开发的:实际上就是将所有监听器注册到广播器中,并通过监听该事件的监听器来处理时间的。结合前面十二篇文章我们将Spring容器、容器扩展、容器扩展点、事件驱动全部基本上都介绍了。
今天我们看下Spring是如何初始化非延迟加载单例的Bean
首先我先回到refresh方法中:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing. 1、初始化上下文信息,替换占位符、必要参数的校验
prepareRefresh();
// Tell the subclass to refresh the internal bean factory. 2、解析类Xml、初始化BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 这一步主要是对初级容器的基础设计
// Prepare the bean factory for use in this context. 3、准备BeanFactory内容:
prepareBeanFactory(beanFactory); // 对beanFactory容器的功能的扩展:
try {
// Allows post-processing of the bean factory in context subclasses. 4、扩展点加一:空实现,主要用于处理特殊Bean的后置处理器
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context. 5、spring bean容器的后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation. 6、注册bean的后置处理器
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context. 7、初始化消息源
initMessageSource();
// Initialize event multicaster for this context. 8、初始化事件广播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses. 9、扩展点加一:空实现;主要是在实例化之前做些bean初始化扩展
onRefresh();
// Check for listener beans and register them. 10、初始化监听器
registerListeners();
//!!!!!!!!!!!! 这里 这里 今天看这里 !!!!!!!!!!!//
// Instantiate all remaining (non-lazy-init) singletons.
// 11、实例化:非懒加载Bean
finishBeanFactoryInitialization(beanFactory);
//!!!!!!!!!!!! 这里 这里 今天看这里 !!!!!!!!!!!//
// Last step: publish corresponding event. 12、发布相应的事件通知
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();
}
}
}
我们将目光回到refresh方法中的,finishBeanFactoryInitialization方法:
初始化非懒加载单例bean
/**
*
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
* 完成上下文的Bean工厂初始化,初始化所有剩余的单例Bean。
*
* 完成Spring应用上下文的Bean工厂初始化。具体步骤包括:
*
* 初始化转换服务(如果存在)。
* 注册默认的嵌入值解析器(如果之前没有注册)。
* 提前初始化LoadTimeWeaverAware Bean。
* 停止使用临时类加载器。
* 冻结Bean工厂配置,防止进一步的更改。
* 实例化所有剩余的单例Bean。
* 这些步骤确保了Spring上下文在初始化过程中所有必要的Bean和服务都已正确配置并实例化。
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
// 初始化 conversion service
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
// 注册默认的embedded解析器:该解析器使用环境变量解析占位符
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
// 初始化 LoadTimeWeaverAware Bean:
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
// 停止使用临时类加载器:
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
// 冻结Bean工厂配置:这一步是为了保证在实例化bean之前配置不在改变
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// 实例化所有非懒加载单例bean
beanFactory.preInstantiateSingletons();
}
上述代码注释很清晰,finishBeanFactoryInitialization方法其实只是做了一些比较基础的初始化工作,核心还得看下preInstantiateSingletons方法。
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 非抽象类、单例非懒加载类,立即初始化;spring,默认都是懒加载需手动设置非懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
// 如果它是 FactoryBean,则需要进一步检查是否实现了 SmartFactoryBean 接口,并决定是否急切初始化实际的 Bean 实例。
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
// 如果不是 FactoryBean,则直接获取 Bean 实例,从而触发其初始化。
else {
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
// 触发初始化回调:
for (String beanName : beanNames) {
// 遍历所有 Bean 定义,检查每个单例实例是否实现了 SmartInitializingSingleton 接口。
Object singletonInstance = getSingleton(beanName);
// 如果实现了 SmartInitializingSingleton 接口,则调用其 afterSingletonsInstantiated 方法
// 以便在所有单例 Bean 实例化之后执行特定的初始化逻辑。
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
上述内容,首先是遍历所有已经注册到Spring容器中的BeanDefiniton对象(在obtainBeanFactroy中注册的),如果BeanDefinniton定义设置的属性满足非懒加载且单例。则需要立马去加载这个对象,同时因为单例这个属性,Spring会在实例化后的Bean放一份单单例缓存中。后续Spring再次使用这个Bean实例的时候,就可以直接从单例缓存中获取这个bean的实例了。
当然默认情况下,配置的Bean都是是不会在Spring容器初始化的时候加载的,除非你在BeanDefiniton属性中显式配置了。如:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="jmUser" class="org.springframework.dto.JmUser" lazy-init="false">
<property name="name" value="测试一" />
<property name="age" value="18" />
</bean>
<!-- 配置自定义监听器 -->
<bean id="myselfListener" class="org.springframework.listener.MyselfListener"/>
</beans>