Spring 源码学习 ② BeanFactory doGetBean 执行流程
Spring 源码系列文章会遵循由浅入深,由易到难,由宏观到微观的原则,目标是尽量降低学习难度,而不是一上来就迷失在源码当中. 文章会从一个场景作为出发点,针对性的目的性极强的针对该场景对 Spring 的实现原理,源码进行探究学习。该系列文章会让你收获什么? 从对 Spring 的使用者成为 Spring 专家。该文章会同步在微信公众号 【DevXJava】, 方便在微信客户端阅读。
本篇的内容是对 BeanFactory
doGetBean
方法的探究,会涉及到一部分源码,但不会大量的讲解源码,目标是让读者对 doGetBean
方法中做的事情和流程有大致的宏观的认识。
场景
public class BeanFactoryGetBeanExp {
public static void main(String[] args) throws Exception {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 在 beanFactory 中注册 bean1
BeanDefinition bdf = BeanDefinitionBuilder.genericBeanDefinition(Bean1.class).getBeanDefinition();
beanFactory.registerBeanDefinition("bean1" , bdf);
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println("bean ----------> " + name);
}
// 调用 getBean , debug 进入观察获取 bean1 过程
Bean1 bean1 = beanFactory.getBean(Bean1.class);
System.out.println(bean1);
}
static class Bean1 {
public Bean1() {
System.out.println("Bean1 默认构造函数执行 >>>>>>>>>>>>>>>>>>>>>>");
}
}
}
这个场景非常简洁,首先我们提供了一个纯净的
DefaultListableBeanFactory
, 通过BeanDefinition
将Bean1
注册到 beanFactory 中; 完成注册后再从 beanFactory 中获取 Bean1 的实例.
为什么不使用ApplicationContext
? 因为ApplicationContext
实际上是对BeanFactory
的封装 , Spring 自身在创建ApplicationContext
会加入很多框架内置的配置。 为了排除干扰所以使用BeanFactory
.
doGetBean 执行过程
BeanFactory
所有的 getBean
方法最终都会去调用 doGetBean
方法, 所以我们只需要关注 doGetBean
方法即可。
上图为
doGetBean
方法的大致执行流程,为了方便和源码对照查看学习,下面会附上doGetBean
的源码;源码中会附上相应的中文注释说明;
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object beanInstance;
// 从单例缓存中获取 bean 实例
// Eagerly check singleton cache for manually registered singletons.
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 实例进行处理
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 没有从单例缓存中获取到实例
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 尝试从父 BeanFactory 中获取 bean , 如果获取到会直接返回
// 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);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 检查 bean 是否存在循环引用 , 并初始化当前 bean 所依赖的 bean 实例
// Guarantee initialization of beans that the current bean depends on.
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 的创建过程
// Create bean instance.
if (mbd.isSingleton()) {
// 尝试从单例缓存(singletonObjects)中获取 bean , 如果没有获取到会进行 bean 的创建
// bean 创建完成后会被存放到单例缓存中 (singletonObjects)
sharedInstance = getSingleton(beanName, () -> {
try {
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;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 对范围为 Prototype 类型的 bean 进行创建,直接调用 createBean 方法进行创建
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// 通过 Scope 对 bean 进行创建
else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
}
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);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
}
}
// bean 创建成功后对 bean 进行类型转换后返回
return adaptBeanInstance(name, beanInstance, requiredType);
}
更详细的细节过程以及源码会在系列文章的后续内容中提供。该文章会同步在微信公众号 【DevXJava】, 方便在微信客户端阅读。
获取完整代码和笔记: https://gitee.com/kernelHP/spring-certified-professional-edu