Spring源码解析之路 Bean加载篇

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: Spring源码解析之路 Bean加载篇

前言

上面一章,说明了bena的解析与注册,这些都是未bean加载做的准备工作,真正复杂的还是bean的加载,但是通过前面的学习,我们也会清楚了各个类在spring容器的职责,这样就可能理解他们的使用,当我们进行扩展时就会更清晰明了,不会看到别人的代码一头雾水,比如下面这段代码的理解

/**
 * 注册bean
 */
public class RegisterBeanFactory implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

        // 注册bean  这里就是省略了解析,因为解析实际上就是构建BeanDefinition
        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(ProxyBeanFactory.class);
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(beanDefinition, "userDao");
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }
}

上面的代码就是手动注册一个bean到容器中,如果看了之前的文章是不是就很明了了呢,现在我们来看看bean的加载

bean加载

从这段代码开始

    BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config.xml");
    UserDao userDao = beanFactory.getBean("userDao", UserDao.class);

getbean方法就是加载的开始,真正的实现就是在AbstractBeanFactory类的doGetBean方法

 protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
        // 提取对应的beanName
        String beanName = this.transformedBeanName(name);
        // 检查缓存中或者实例工厂中是否有对应的实例
        // 原因是创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖
        // Spring的解决方案是不等bean创建完成就会创建bean的ObjectFactory提早曝光
        // 就是将ObjectFactory加入缓存,一旦下一个bean创建时需要依赖上一个bean则直接使用缓存中bean'Factory
        // 直接尝试从缓存获取,或者singletonFactories的ObjectFactory获取
        Object sharedInstance = this.getSingleton(beanName);
        Object beanInstance;
        if (sharedInstance != null && args == null) {
            if (this.logger.isTraceEnabled()) {
                if (this.isSingletonCurrentlyInCreation(beanName)) {
                    this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
                } else {
                    this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }

            beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
        } else {
            // 只有单例模式下才会尝试解决循环依赖,原型模式下如果存在依赖,那么就会抛出异常
            if (this.isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
            
            BeanFactory parentBeanFactory = this.getParentBeanFactory();
            // 如果beanDefitionMap找不到beanName则会尝试从parentBeanFactory中找
            if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
                String nameToLookup = this.originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
                }

                if (args != null) {
                    return parentBeanFactory.getBean(nameToLookup, args);
                }

                if (requiredType != null) {
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }

                return parentBeanFactory.getBean(nameToLookup);
            }

            if (!typeCheckOnly) {
                this.markBeanAsCreated(beanName);
            }

            StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);

            try {
                if (requiredType != null) {
                    beanCreation.tag("beanType", requiredType::toString);
                }
                // 将GenericBeanDefinition转换为RootBeanDefinition,如果指定的bean是子bean那么会合并父bean信息
                RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
                this.checkMergedBeanDefinition(mbd, beanName, args);
                
                String[] dependsOn = mbd.getDependsOn();
                String[] var12;
                // 如存在依赖,就要递归实现依赖的bean
                if (dependsOn != null) {
                    var12 = dependsOn;
                    int var13 = dependsOn.length;

                    for(int var14 = 0; var14 < var13; ++var14) {
                        String dep = var12[var14];
                        if (this.isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        // 缓存以来调用
                        this.registerDependentBean(dep, beanName);

                        try {
                            this.getBean(dep);
                        } catch (NoSuchBeanDefinitionException var31) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var31);
                        }
                    }
                }
                // 实例化依赖的bean后,就开始实例化mbd本身,这个有意思,之前的理解都是本身先实例化
                // 单例模式的创建
                if (mbd.isSingleton()) {
                    sharedInstance = this.getSingleton(beanName, () -> {
                        try {
                            return this.createBean(beanName, mbd, args);
                        } catch (BeansException var5) {
                            this.destroySingleton(beanName);
                            throw var5;
                        }
                    });
                    beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                } else if (mbd.isPrototype()) {
                    // 原型模式创建
                    var12 = null;

                    Object prototypeInstance;
                    try {
                        this.beforePrototypeCreation(beanName);
                        prototypeInstance = this.createBean(beanName, mbd, args);
                    } finally {
                        this.afterPrototypeCreation(beanName);
                    }

                    beanInstance = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                } else {
                    String scopeName = mbd.getScope();
                    if (!StringUtils.hasLength(scopeName)) {
                        throw new IllegalStateException("No scope name defined for bean ��" + beanName + "'");
                    }

                    Scope 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, () -> {
                            this.beforePrototypeCreation(beanName);

                            Object var4;
                            try {
                                var4 = this.createBean(beanName, mbd, args);
                            } finally {
                                this.afterPrototypeCreation(beanName);
                            }

                            return var4;
                        });
                        beanInstance = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    } catch (IllegalStateException var30) {
                        throw new ScopeNotActiveException(beanName, scopeName, var30);
                    }
                }
            } catch (BeansException var32) {
                beanCreation.tag("exception", var32.getClass().toString());
                beanCreation.tag("message", String.valueOf(var32.getMessage()));
                this.cleanupAfterBeanCreationFailure(beanName);
                throw var32;
            } finally {
                beanCreation.end();
            }
        }

        return this.adaptBeanInstance(name, beanInstance, requiredType);
    }

以上代码就是spring加载bean的过程,下面我们来一步步分析一下

  1. 转换对应的beanName

    这部分对应的就是transformedBeanName方法

          /**
          *返回实际的 bean 名称,去掉工厂引用 * 前缀(如果有,也去掉重复的工厂前缀,如果找到)。                 * @param name bean 的名称 * @return 转换后的名称 * @see *BeanFactory#FACTORY_BEAN_PREFIX
           */
          public static String transformedBeanName(String name) {
                  Assert.notNull(name, "'name' must not be null");
                  if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
                          return name;
                  }
                  return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
                          do {
                                  beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
                          }
                          while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
                          return beanName;
                  });
          }
    
      

    既然我们之间解析和注册的时候已经明确了beanName那么为什么还要转换呢,从这个方法的注释我们可以知道,beanName有可能有前缀如&,那么这样就要把他去掉,另外我们定义bean的时候可能会用到alias别名,这里的别名就要进行转换,比如别名A指向beanB,那么别名A要返回beanB

  2. 尝试从缓存中加载依赖

    这部分主要是为了解决循环依赖,单例的情况下,解决依赖的方式就是,在spring bean还没加载完,就将他里面的对象先放到缓存中ObjectFactory,读取的时候如果缓存里面有就从缓存里面读取,如果没有就从singletonFactories中读取。

  3. bean的实例化

    这一步时我们可能有一个疑问,bean不是已经在解析和注册时已经实例化到缓存BeanDefinitionResitry中了吗?为什么还要再实例化,那是因为解析和注册后我们得到的是初始状态的bean,而我们真正需要的bean是facoty-mthod返回的bean,他的创建是由getObjectForBeanInstance方法来完成的

  4. 原型模式下判断循环依赖

    spring会对循环依赖处理都是在单例模式下,如果原型模式出现了这种情况会直接抛出异常

  5. 检测parentBeanFactory

    如果当前的缓存中没有找到beanName的配置,那么就去parentBeanFactory中查找,找到后再通过递归调用getBean方法。

  6. 存储xml文件的GernericBeanDefinition转换为RootBeanDefinition

    spring的后续处理都是针对RootBeanDefinition进行处理的,所以我们要把解析后的GernericBeanDefinition转换成RootBeanDefinition

  7. 寻找依赖

    spring bean的创建过程中,要先创建bean中的属性,比如depends-on="jedisPoolConfig"

     <!-- jedis pool配置 -->
     <bean id="jedisPool" class="redis.clients.jedis.JedisPool" destroy-method="destroy" depends-on="jedisPoolConfig">
      <constructor-arg ref="jedisPoolConfig" />  
      <constructor-arg value="127.0.0.1" />  
      <constructor-arg type="int" value="6379" />  
     </bean>
    

depends-on="jedisPoolConfig" 在实例话前加载

  1. 针对不同的scope进行加载

    singleton,prototype,request多种scope

获取单例bean

从前面的代码中了解到,单例在spring容器只会创建一次,后续都是从缓存或者singletonFactoty中获取,为了解决循环依赖,spring会在不等bean创建完成就将创建bena的beanFactory提早曝光,下面看看他的实现
getSingleton方法

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
                Assert.notNull(beanName, "Bean name must not be null");
                // 锁定全局变量并进行处理
                synchronized (this.singletonObjects) {
                        // 缓存中是否存在实例
                        Object singletonObject = this.singletonObjects.get(beanName);
                        if (singletonObject == null) {
                              
                                if (this.singletonsCurrentlyInDestruction) {
                                        throw new BeanCreationNotAllowedException(beanName,
                                                        "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                                                        "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
                                }
                                if (logger.isDebugEnabled()) {
                                        logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                                }
                                beforeSingletonCreation(beanName);
                                boolean newSingleton = false;
                                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                                if (recordSuppressedExceptions) {
                                        this.suppressedExceptions = new LinkedHashSet<>();
                                }
                                try {   
                                        // 调用预先设定的getObjct方法
                                        singletonObject = singletonFactory.getObject();
                                        newSingleton = true;
                                }
                                catch (IllegalStateException ex) {
                                        // Has the singleton object implicitly appeared in the meantime ->
                                        // if yes, proceed with it since the exception indicates that state.
                                        singletonObject = this.singletonObjects.get(beanName);
                                        if (singletonObject == null) {
                                                throw ex;
                                        }
                                }
                                catch (BeanCreationException ex) {
                                        if (recordSuppressedExceptions) {
                                                for (Exception suppressedException : this.suppressedExceptions) {
                                                        ex.addRelatedCause(suppressedException);
                                                }
                                        }
                                        throw ex;
                                }
                                finally {
                                        if (recordSuppressedExceptions) {
                                                this.suppressedExceptions = null;
                                        }
                                        afterSingletonCreation(beanName);
                                }
                                if (newSingleton) {
                                        // 记录到缓存中
                                        addSingleton(beanName, singletonObject);
                                }
                        }
                        return singletonObject;
                }
}

从bean实例中获取对象

在这一步前面的过程分别是 解析-注册-从不同的scope中获取bean,那么这一步就是终极加载,前面的流程中获得的bean其实都是初始状态的bean,而这一步就是要在前面的基础上加料了,这一步对应的方法就是getObjectForBeanInstance方法

protected Object getObjectForBeanInstance(
                        Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

                // 如果指定的name是工厂相关&前缀,且beanInstace又不是Factory则验证不通过
      
                if (BeanFactoryUtils.isFactoryDereference(name)) {
                        if (beanInstance instanceof NullBean) {
                                return beanInstance;
                        }
                        if (!(beanInstance instanceof FactoryBean)) {
                                throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
                        }
                        if (mbd != null) {
                                mbd.isFactoryBean = true;
                        }
                        return beanInstance;
                }

                // Now we have the bean instance, which may be a normal bean or a FactoryBean.
                // If it's a FactoryBean, we use it to create a bean instance, unless the
                // caller actually wants a reference to the factory.
                if (!(beanInstance instanceof FactoryBean)) {
                        return beanInstance;
                }

                Object object = null;
                if (mbd != null) {
                        mbd.isFactoryBean = true;
                }
                else {  
                        // 尝试从缓存中加载
                        object = getCachedObjectForFactoryBean(beanName);
                }
                if (object == null) {
                        // Return bean instance from factory. 明确知道beanInstance是Factory类型
                        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
                        // Caches object obtained from FactoryBean if it is a singleton.
                        if (mbd == null && containsBeanDefinition(beanName)) {
                                // 父类合并
                                mbd = getMergedLocalBeanDefinition(beanName);
                        }
                        boolean synthetic = (mbd != null && mbd.isSynthetic());
                        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
                }
                return object;
        }
        

主要工作就是

  • 对FactoryBean进行验证
  • 对非FactoryBean不做处理
  • 对bean进行转换
  • 最后委托给getObjectFromFactoryBean方法
         protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
                if (factory.isSingleton() && containsSingleton(beanName)) {
                        synchronized (getSingletonMutex()) {
                                Object object = this.factoryBeanObjectCache.get(beanName);
                                if (object == null) {
                                        object = doGetObjectFromFactoryBean(factory, beanName);
                                        // Only post-process and store if not put there already during getObject() call above
                                        // (e.g. because of circular reference processing triggered by custom getBean calls)
                                        Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                                        if (alreadyThere != null) {
                                                object = alreadyThere;
                                        }
                                        else {
                                                if (shouldPostProcess) {
                                                        if (isSingletonCurrentlyInCreation(beanName)) {
                                                                // Temporarily return non-post-processed object, not storing it yet..
                                                                return object;
                                                        }
                                                        beforeSingletonCreation(beanName);
                                                        try {
                                                                object = postProcessObjectFromFactoryBean(object, beanName);
                                                        }
                                                        catch (Throwable ex) {
                                                                throw new BeanCreationException(beanName,
                                                                                "Post-processing of FactoryBean's singleton object failed", ex);
                                                        }
                                                        finally {
                                                                afterSingletonCreation(beanName);
                                                        }
                                                }
                                                if (containsSingleton(beanName)) {
                                                        this.factoryBeanObjectCache.put(beanName, object);
                                                }
                                        }
                                }
                                return object;
                        }
                }
                else {
                        // 这里面直接调动了FactotyBean的getObject方法
                        Object object = doGetObjectFromFactoryBean(factory, beanName);
                        if (shouldPostProcess) {
                                try {   
                                        // 调用ObjectFactory的后置处理器
                                        object = postProcessObjectFromFactoryBean(object, beanName);
                                }
                                catch (Throwable ex) {
                                        throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
                                }
                        }
                        return object;
                }
        }

从代码中可以看出,其实在加载完bean后又执行了一个调用后置处理器的操作,这个操作就是为了以后对spring加载bean的灵活拓展

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}
相关文章
|
16天前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
16天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
16天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是"将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为5种:单例模式、工厂方法模式抽象工厂式、原型模式、建造者模式。
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
2天前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
7月前
|
Java 开发者 Spring
解析Spring中Bean的生命周期
解析Spring中Bean的生命周期
65 2
|
7月前
|
XML druid Java
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
81 0
|
3月前
|
Java 开发者 Spring
Spring bean的生命周期详解!
本文详细解析Spring Bean的生命周期及其核心概念,并深入源码分析。Spring Bean是Spring框架的核心,由容器管理其生命周期。从实例化到销毁,共经历十个阶段,包括属性赋值、接口回调、初始化及销毁等。通过剖析`BeanFactory`、`ApplicationContext`等关键接口与类,帮助你深入了解Spring Bean的管理机制。希望本文能助你更好地掌握Spring Bean生命周期。
164 1
|
3月前
|
Java 开发者 Spring
Spring bean的生命周期详解!
本文详细介绍了Spring框架中的核心概念——Spring Bean的生命周期,包括实例化、属性赋值、接口回调、初始化、使用及销毁等10个阶段,并深入剖析了相关源码,如`BeanFactory`、`DefaultListableBeanFactory`和`BeanPostProcessor`等关键类与接口。通过理解这些核心组件,读者可以更好地掌握Spring Bean的管理和控制机制。
130 1
|
6月前
|
Java Spring 容器
Spring Boot 启动源码解析结合Spring Bean生命周期分析
Spring Boot 启动源码解析结合Spring Bean生命周期分析
121 11
|
5月前
|
前端开发 Java 开发者

推荐镜像

更多
下一篇
开通oss服务