ITPub博客

首页 > 数据库 > 数据库开发技术 > Spring 源码学习 ② BeanFactory doGetBean 执行流程

Spring 源码学习 ② BeanFactory doGetBean 执行流程

原创 数据库开发技术 作者:DevXTalk 时间:2023-01-15 22:14:53 0 删除 编辑

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 方法即可。

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

                                       

DevXJava




原文作者:DevXTalk;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2019-03-23

  • 博文量
    178
  • 访问量
    82586