一、源码前准备
1、刨析源码的好处
提高培养代码架构思维、深入理解框架。
2、源码刨析原则
1)定焦原则
抓主线。
2)宏观原则
站在上帝视角,关注源码结构和业务流程(淡化具体某行代码的编码细节)。
3、读源码的方法和技巧
1)断点
观察调用栈。
2)反调
Find Usages。
3)经验
spring 框架中 doXXX,做具体处理的地方。
4、Spring 源码构建
- 下载源码(github)。
- 安装 gradle 5.6.3(类似于maven) Idea 2019.1 Jdk 11.0.5
- 导入(耗费一定时间)
- 编译工程(顺序:core - oxm - context - beans - aspects - aop)
点击:工程 —> tasks —> compileTestJava
5、Spring IoC 容器体系
- IoC 容器是 Spring 的核心模块,是抽象了对象管理、依赖关系管理的框架解决方案。
- Spring 提供了很多的容器,其中 BeanFactory 是顶层容器(根容器),不能被实例化,它定义了所有 IoC 容器必须遵从的一套原则,具体的容器实现可以增加额外的功能,比如我们常用到的 ApplicationContext,其下更具体的实现如 ClassPathXmlApplicationContext 包含了解析 xml 等一系列的内容,AnnotationConfigApplicationContext 则是包含了注解解析等一系列的内容。
- Spring IoC 容器继承体系非常聪明,需要使用哪个层次用哪个层次即可,不必使用功能大而全的。
BeanFactory 顶级接口方法栈如下:
BeanFactory 容器继承体系:
通过其接口设计,我们可以看到我们一贯使用的 ApplicationContext 除了继承 BeanFactory 的子接口,还继承了 ResourceLoader、MessageSource 等接口,因此其提供的功能也就更丰富了。
下面我们以 ClasspathXmlApplicationContext 为例,深入源码说明 IoC 容器的初始化流程。
6、Bean 生命周期关键时机点
1)LagouBean 类
public class LagouBean implements InitializingBean {
public LagouBean(){
System.out.println("LagouBean 构造器...");
}
/**
* InitializingBean 接口实现
*/
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("LagouBean afterPropertiesSet...");
}
public void print() {
System.out.println("print方法业务逻辑执行");
}
}
2)BeanPostProcessor 接口实现类
public class MyBeanPostProcessor implements BeanPostProcessor {
public MyBeanPostProcessor() {
System.out.println("BeanPostProcessor 实现类构造函数...");
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if("lagouBean".equals(beanName)) {
System.out.println("BeanPostProcessor 实现类 postProcessBeforeInitialization 方法被调用中......");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if("lagouBean".equals(beanName)) {
System.out.println("BeanPostProcessor 实现类 postProcessAfterInitialization 方法被调用中......");
}
return bean;
}
}
3)BeanFactoryPostProcessor 接口实现类
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public MyBeanFactoryPostProcessor() {
System.out.println("BeanFactoryPostProcessor的实现类构造函数...");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
System.out.println("BeanFactoryPostProcessor的实现方法调用中......");
}
}
4)applicationContext.xml
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
">
<bean id="lagouBean" class="com.lagou.LagouBean"/>
<bean id="myBeanFactoryPostProcessor" class="com.lagou.MyBeanFactoryPostProcessor"/>
<bean id="myBeanPostProcessor" class="com.lagou.MyBeanPostProcessor"/>
</beans>
5)IoC 容器源码分析用例
@Test
public void testIoC() {
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
LagouBean lagouBean = applicationContext.getBean(LagouBean.class);
System.out.println(lagouBean);
}
6)分析调用情况
通过在关键时机节点打断点,观察调用栈,查看主要关键代码在哪。
我们发现 Bean 对象创建的几个关键时机点代码层级的调用都在 AbstractApplicationContext 类的 refresh 方法中。
关键点 | 触发代码 |
---|---|
构造器 | refresh#finishBeanFactoryInitialization(beanFactory) |
InitializingBean 方法调用 | refresh#finishBeanFactoryInitialization(beanFactory) |
BeanFactoryPostProcessor 初始化 | refresh#invokeBeanFactoryPostProcessors(beanFactory) |
BeanFactoryPostProcessor 方法调用 | refresh#invokeBeanFactoryPostProcessors(beanFactory) |
BeanPostProcessor 初始化 | refresh#registerBeanPostProcessors(beanFactory) |
BeanPostProcessor 方法调用 | refresh#finishBeanFactoryInitialization(beanFactory) |
7、Spring IoC 容器初始化主流程
由上分析可知,Spring IoC 容器初始化的关键环节就在 AbstractApplicationContext#refresh() 方法中,我们查看 refresh 方法来俯瞰容器创建的主体流程,主体流程下的具体子流程我们后面再来讨论。
@Override
public void refresh() throws BeansException, IllegalStateException {
// 对象锁加锁
synchronized (this.startupShutdownMonitor) {
/*
Prepare this context for refreshing.
第一步:刷新前的预处理
表示在真正做 refresh 操作之前需要准备做的事情:
设置 Spring 容器的启动时间,
开启活跃状态,撤销关闭状态
验证环境信息里一些必须存在的属性等
*/
prepareRefresh();
/*
Tell the subclass to refresh the internal bean factory.
第二步:
获取 BeanFactory;默认实现是 DefaultListableBeanFactory
加载 BeanDefition 并注册到 BeanDefitionRegistry
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
/*
Prepare the bean factory for use in this context.
第三步:
BeanFactory 的预准备工作
(BeanFactory 进行一些设置,比如 context 的类加载器等)
*/
prepareBeanFactory(beanFactory);
try {
/*
Allows post-processing of the bean factory in context subclasses.
第四步:BeanFactory 准备工作完成后进行的后置处理工作
*/
postProcessBeanFactory(beanFactory);
/*
Invoke factory processors registered as beans in the context.
第五步:实例化实现了 BeanFactoryPostProcessor 接口的 Bean,并调用接口方法
*/
invokeBeanFactoryPostProcessors(beanFactory);
/*
Register bean processors that intercept bean creation.
第六步:注册 BeanPostProcessor(Bean 的后置处理器),在创建 bean 的前后等执行
*/
registerBeanPostProcessors(beanFactory);
/*
Initialize message source for this context.
第七步:初始化 MessageSource 组件(做国际化功能;消息绑定,消息解析);
*/
initMessageSource();
/*
Initialize event multicaster for this context.
第八步:初始化事件派发器
*/
initApplicationEventMulticaster();
/*
Initialize other special beans in specific context subclasses.
第九步:子类重写这个方法,在容器刷新的时候可以自定义逻辑;
如创建 Tomcat,Jetty 等 WEB 服务器
*/
onRefresh();
/*
Check for listener beans and register them.
第十步:注册应用的监听器。就是注册实现了 ApplicationListener 接口的监听器 bean
*/
registerListeners();
/*
Instantiate all remaining (non-lazy-init) singletons.
第十一步:
初始化所有剩下的非懒加载的单例 bean
初始化创建非懒加载方式的单例 Bean 实例(未设置属性)
填充属性
初始化方法调用(比如调用 afterPropertiesSet 方法、init-method 方法)
调用 BeanPostProcessor(后置处理器)对实例 bean 进行后置处理
*/
finishBeanFactoryInitialization(beanFactory);
/*
Last step: publish corresponding event.
第十二步:
完成 context 的刷新。主要是调用 LifecycleProcessor 的 onRefresh() 方法,
并且发布事件(ContextRefreshedEvent)
*/
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();
}
}
}
二、BeanFactory 创建流程
1、获取 BeanFactory 子流程
过程比较简单,直接上时序图:
2、BeanDefinition 加载解析及注册子流程
1)该子流程涉及到如下几个关键步骤:
Resource 定位:指对 BeanDefinition 的资源定位过程。通俗讲就是找到定义 Javabean 信息的 XML 文件,并将其封装成 Resource 对象。
BeanDefinition 载入:把用户定义好的 Javabean 表示为 IoC 容器内部的数据结构,这个容器内部的数据结构就是 BeanDefinition。
注册 BeanDefinition 到 IoC 容器。
2)过程分析
Step 1:子流程入口地址
AbstractRefreshableApplicationContext#refreshBeanFactory
@Override
protected final void refreshBeanFactory() throws BeansException {
// 判断是否已有 bean factory
if (hasBeanFactory()) {
// 销毁 beans
destroyBeans();
// 关闭 bean factory
closeBeanFactory();
}
try {
// 实例化 DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 设置序列化 id
beanFactory.setSerializationId(getId());
// 自定义 bean 工厂的一些属性(是否覆盖、是否允许循环依赖)
customizeBeanFactory(beanFactory);
// 加载应用中的 BeanDefinitions
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
// 赋值当前 bean facotry
this.beanFactory = beanFactory;
}
} catch (IOException ex) {
throw new ApplicationContextException(
"I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
其上第 18 行调用 loadBeanDefinitions 正是入口所在。
Step 2:依次调用多个类的 loadBeanDefinitions 方法
AbstractXmlApplicationContext -> AbstractBeanDefinitionReader -> XmlBeanDefinitionReader -> 最后到达的 XmlBeanDefinitionReader#doLoadBeanDefinitions
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 读取 xml 信息,将 xml 中信息保存到 Document 对象
Document doc = doLoadDocument(inputSource, resource);
// 解析 document 对象,封装 BeanDefinition 对象并进行注册
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}
Step 3:我们重点观察 XmlBeanDefinitionReader 类的 registerBeanDefinitions 方法。
public int registerBeanDefinitions(Document doc, Resource resource)
throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
// 获取已有 BeanDefinition 的数量
int countBefore = getRegistry().getBeanDefinitionCount();
// 注册 BeanDefinition
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
// 返回新注册的 BeanDefinition 数量
return getRegistry().getBeanDefinitionCount() - countBefore;
}
此处我们关注两个地方:
- createRederContext 方法。
- DefaultBeanDefinitionDocumentReader 类的
registerBeanDefinitions 方法,
a. 先进入 createRederContext 方法看看:
XmlBeanDefinitionReader#createRederContext
public XmlReaderContext createReaderContext(Resource resource) {
return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
this.sourceExtractor, this, getNamespaceHandlerResolver());
}
XmlBeanDefinitionReader#getNamespaceHandlerResolver
public NamespaceHandlerResolver getNamespaceHandlerResolver() {
if (this.namespaceHandlerResolver == null) {
this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
}
return this.namespaceHandlerResolver;
}
XmlBeanDefinitionReader#createDefaultNamespaceHandlerResolver
protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
ClassLoader cl = (getResourceLoader() != null ?
getResourceLoader().getClassLoader() : getBeanClassLoader());
return new DefaultNamespaceHandlerResolver(cl);
}
我们可以看到,此处 Spring 首先完成了 NamespaceHandlerResolver 的初始化。
b. 再进入 registerBeanDefinitions 方法中追踪:
DefaultBeanDefinitionDocumentReader#registerBeanDefinitions
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
doRegisterBeanDefinitions(doc.getDocumentElement());
}
DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipped XML bean definition file due to specified profiles ["
+ profileSpec + "] not matching: "
+ getReaderContext().getResource());
}
return;
}
}
}
preProcessXml(root);
// 重点是 parseBeanDefinitions 方法
// preProcessXml 和 postProcessXml 都是钩子方法
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
DefaultBeanDefinitionDocumentReader#parseBeanDefinitions
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
// 解析默认标签元素
parseDefaultElement(ele, delegate);
} else {
// 解析自定义标签元素
delegate.parseCustomElement(ele);
}
}
}
} else {
delegate.parseCustomElement(root);
}
}
DefaultBeanDefinitionDocumentReader#parseDefaultElement
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
// import 元素处理
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
// alias 元素处理
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
// bean 元素处理
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
// 解析 bean 元素
processBeanDefinition(ele, delegate);
}
// 嵌套 beans 处理
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
DefaultBeanDefinitionDocumentReader#processBeanDefinition
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 解析 bean 元素为 BeanDefinition,但是此时使用 BeanDefinitionHolder
// 又包装成了 BeanDefinitionHolder 对象
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
/*
<bean id="demo" class="com.chenhao.spring.MyTestBean">
<property name="beanName" value="bean demo1"/>
<meta key="demo" value="demo"/>
<mybean:username="mybean"/>
</bean>
如果有自定义标签,则处理自定义标签
*/
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 完成 BeanDefinition 的注册
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder,
getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
至此,注册流程结束,我们发现,所谓的注册就是把封装的 XML 中定义的 Bean 信息封装为 BeanDefinition 对象之后放入一个 Map 中,BeanFactory 是以 Map 的结构组织这些 BeanDefinition 的。
DefaultListableBeanFactory 中相关的代码:
/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
// 其他代码省略,
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
3)时序图
三、Bean 创建流程
1、起始点
通过最开始的关键时机点分析,我们知道 Bean 创建子流程入口在 AbstractApplicationContext#refresh() 方法的 finishBeanFactoryInitialization(beanFactory) 处。
/*
Instantiate all remaining (non-lazy-init) singletons.
初始化所有剩下的非懒加载的单例bean
初始化创建非懒加载方式的单例Bean实例(未设置属性)
填充属性
初始化方法调用(比如调用afterPropertiesSet方法、init-method方法)
调用 BeanPostProcessor(后置处理器)对实例bean进行后置处理
*/
finishBeanFactoryInitialization(beanFactory);
2、过程
进入 AbstractApplicationContext#finishBeanFactoryInitialization
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
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));
}
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal ->
getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering
// their transformers early.
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.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// 实例化所有立即加载的单例bean
beanFactory.preInstantiateSingletons();
}
进入 DefaultListableBeanFactory#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.
// 所有 bean 的名字
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
// 触发所有非延迟加载单例 bean 的初始化,主要步骤为 getBean
for (String beanName : beanNames) {
// 合并父 BeanDefinition 对象
// map.get(beanName)
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 判断是否是懒加载单例 bean,如果是单例的并且不是懒加载的则在容器创建时初始化
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 判断是否是 FactoryBean
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
// 如果是 FactoryBean 则加 &
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);
}
}
}
else {
// 实例化当前 bean
/*
如果是普通 bean 则进行初始化并依赖注入,此 getBean(beanName) 接下来触发的逻辑
和懒加载时 context.getBean("beanName") 所触发的逻辑是一样的
*/
getBean(beanName);
}
}
}
// 代码略...
}
AbstractBeanFactory#getBean
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
AbstractBeanFactory#doGetBean
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 解析 beanName 如果以&开头去掉&开头,如果是别名获取到真正的名字
final String beanName = transformedBeanName(name);
Object bean;
// 单纯理解尝试从缓存中获取 bean
Object sharedInstance = getSingleton(beanName);
// 如果已经存在则返回
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
} else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 针对 FactoryBean 的处理
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// 如果是 prototype 类型且开启允许循环依赖,则抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 检查父工厂中是否存在该对象
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
} else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
} else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 合并父子bean 属性
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 处理dependsOn配置
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName
+ "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 创建单例bean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建 bean
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
// 创建原型 bean 之前添加标记
beforePrototypeCreation(beanName);
// 创建原型 bean
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 创建原型 bean 之后删除标记
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '"
+ scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to"
+ " it from a singleton", ex);
}
}
} catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 代码略...
return (T) bean;
}
AbstractAutowireCapableBeanFactory#createBean
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
// 拿到 Bd
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
// 获得类信息
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
} catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
} catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 进入,真真正正创建bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
} catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
} catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName,
"Unexpected exception during bean creation", ex);
}
}
AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd,
final @Nullable Object[] args) throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 创建 Bean 实例,仅仅调用构造方法,但是尚未设置属性
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 初始化 bean 实例
Object exposedObject = bean;
try {
// Bean属性填充
populateBean(beanName, mbd, instanceWrapper);
// 调用初始化方法,应用 BeanPostProcessor 后置处理器
exposedObject = initializeBean(beanName, exposedObject, mbd);
} catch (Throwable ex) {
if (ex instanceof BeanCreationException
&& beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
} else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
// 代码略...
return exposedObject;
}
四、 lazy-init 延迟加载机制原理
1、分析
- 普通 Bean 的初始化是在容器启动初始化阶段执行的,而被 lazy-init=true 修饰的 bean 则是在从容器里第一次进行 context.getBean() 时进行触发。
- Spring 启动的时候会把所有 bean 信息(包括 XML 和注解)解析转化成 Spring 能够识别的 BeanDefinition 并存到 Hashmap 里供下面的初始化时用,然后对每个 BeanDefinition 进行处理,
- 如果是懒加载的则在容器初始化阶段不处理,其他的则在容器初始化阶段进行初始化并依赖注入。
重看代码 DefaultListableBeanFactory#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.
// 所有 bean 的名字
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
// 触发所有非延迟加载单例 bean 的初始化,主要步骤为 getBean
for (String beanName : beanNames) {
// 合并父 BeanDefinition 对象
// map.get(beanName)
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 判断是否是懒加载单例 bean,如果是单例的并且不是懒加载的则在容器创建时初始化
// 懒加载不会进行以下代码
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 判断是否是 FactoryBean
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
// 如果是 FactoryBean 则加 &
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);
}
}
}
else {
// 实例化当前 bean
/*
如果是普通 bean 则进行初始化并依赖注入,此 getBean(beanName) 接下来触发的逻辑
和懒加载时 context.getBean("beanName") 所触发的逻辑是一样的
*/
getBean(beanName);
}
}
}
// 代码略...
}
2、总结
- 对于被修饰为 lazy-init 的 bean, Spring 容器初始化阶段不会进行 init 并且依赖注入,当第一次进行 getBean 时候才进行初始化并依赖注入。
- 对于非懒加载的 bean,getBean 的时候会从缓存里头获取,因为容器初始化阶段 Bean 已经初始化完成并缓存了起来。
文章内容输出来源:拉勾教育Java高薪训练营;