Spring IOC源码分析(七):IOC容器的对象存储体系与bean对象的加载流程

本文主要是介绍Spring IOC源码分析(七):IOC容器的对象存储体系与bean对象的加载流程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、IOC容器的对象存储体系

1. 获取bean对象

  • spring主要通过BeanFactory接口的getBean方法来从IOC容器,即BeanFactory的实现类中获取某个bean对象实例,如下为BeanFactory的getBean方法定义:

    public interface BeanFactory {.../*** Return an instance, which may be shared or independent, of the specified bean.* <p>This method allows a Spring BeanFactory to be used as a replacement for the* Singleton or Prototype design pattern. Callers may retain references to* returned objects in the case of Singleton beans.* <p>Translates aliases back to the corresponding canonical bean name.* Will ask the parent factory if the bean cannot be found in this factory instance.* @param name the name of the bean to retrieve* @return an instance of the bean* @throws NoSuchBeanDefinitionException if there is no bean definition* with the specified name* @throws BeansException if the bean could not be obtained*/// getBean方法的其中一个版本 // 获取name对应的bean对象实例,如果是单例的则直接返回,原型的则每次创建一个新的bean对象实例Object getBean(String name) throws BeansException;...}
    
  • 在BeanFactory接口的具体实现类中,通过类型为ConcurrentHashMap的容器map来保存beanName和bean对象实例的映射。

  • 在接口设计层面,BeanFactory接口并不直接定义该映射map,只是定义从该映射map获取bean对象的方法,而是抽象了一个BeanRegistry的概念,分别在SingletonBeanRegistry定义单例bean对象的映射map和在FactoryBeanRegistrySupport定义了由FactoryBean创建的bean对象的映射map;然后BeanFactory接口的具体实现类同时实现BeanFactory接口和BeanRegistry概念的接口SingletonBeanRegistry和FactoryBeanRegistrySupport,从而实现一个完整的IOC容器,类似于使用了一种读写分离的方式来进行接口拓展。

2. 注册bean对象

  • 单例bean对象容器SingletonBeanRegistry:定义了registerSingleton注册bean对象到IOC容器中。

    public interface SingletonBeanRegistry {/*** Register the given existing object as singleton in the bean registry,* under the given bean name.* <p>The given instance is supposed to be fully initialized; the registry* will not perform any initialization callbacks (in particular, it won't* call InitializingBean's {@code afterPropertiesSet} method).* The given instance will not receive any destruction callbacks* (like DisposableBean's {@code destroy} method) either.* <p>When running within a full BeanFactory: <b>Register a bean definition* instead of an existing instance if your bean is supposed to receive* initialization and/or destruction callbacks.</b>* <p>Typically invoked during registry configuration, but can also be used* for runtime registration of singletons. As a consequence, a registry* implementation should synchronize singleton access; it will have to do* this anyway if it supports a BeanFactory's lazy initialization of singletons.* @param beanName the name of the bean* @param singletonObject the existing singleton object* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet* @see org.springframework.beans.factory.DisposableBean#destroy* @see org.springframework.beans.factory.support.BeanDefinitionRegistry#registerBeanDefinition*/void registerSingleton(String beanName, Object singletonObject);...}
    
  1. SingletonBeanRegistry接口实现类DefaultSingletonBeanRegistry

    public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {/** Cache of singleton objects: bean name to bean instance. */private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);...}
    
  2. FactoryBean创建的bean对象容器FactoryBeanRegistrySupport:继承于DefaultSingletonBeanRegistry,映射map中的bean对象实例是通过调用FactoryBean的getObject方法获取的bean对象。

    public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry {/** Cache of singleton objects created by FactoryBeans: FactoryBean name to object. */private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);...}
    

3. 完整的IOC容器

  • BeanFactory的基础抽象实现类:AbstractBeanFactory,AbstractBeanFactory继承了以上的BeanFactory接口和
    SingletonBeanRegistry接口。

    public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {...}
    

二、IOC容器中bean对象的加载流程

在spring的体系结构设计当中,主要通过ApplicationContext来对外提供IOC服务,即与应用代码集成,而不是在应用代码中直接使用BeanFactory。通过ApplicationContext来初始化BeanFactory和从BeanFactory获取应用所需的bean对象。

1. 加载流程的启动:IOC容器上下文的refresh方法

  • ApplicationContext的生命周期如下:具体在AbstractApplicationContext的refresh方法定义。

    public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 为beanFactory添加内部的BeanPostProcessor的bean对象等// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// 从beanFactory的beanDefinitions中获取实现了BeanPostProcessor接口的beanDefinition,// 然后创建bean对象,添加到beanFactory// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}...}
    }
    
  • 在finishBeanFactoryInitialization方法是创建单例bean对象,在这里涉及到bean对象的整个创建流程。

  • bean对象的创建是在调用了BeanFactory的getBean方法触发的,即如果指定beanName的bean对象不存在,则开始创建该bean对象实例,如下为AbstractBeanFactory的getBean方法定义:

    public Object getBean(String name) throws BeansException {// doGetBean底层调用createBean方法创建bean对象实例return doGetBean(name, null, null, false);
    }
    

2. BeanFactory中普通bean对象的创建:不是FactoryBean创建的bean对象

  • 注意以下过程是正常bean对象的创建过程,不是由FactoryBean创建bean对象的过程。FactoryBean创建bean对象是在自身的getObject方法实现的。

  • 底层关于bean对象实例创建的核心方法为createBean:如下为AbstractAutowireCapableBeanFactory的createBean方法定义:核心过程为首先进行类加载,然后检查是否创建代理对象替代该bean对象,如果是则创建代理对象之间返回,否则进入bean对象的正常创建流程,具体在doCreateBean方法定义。

    /*** Central method of this class: creates a bean instance,* populates the bean instance, applies post-processors, etc.* @see #doCreateBean*/
    @Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {if (logger.isTraceEnabled()) {logger.trace("Creating instance of bean '" + beanName + "'");}RootBeanDefinition mbdToUse = mbd;// 为给定bean进行类加载// 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.// 调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation// (如果创建了bean,则还要调用BeanPostProcessor的postProcessAfterInitialization)// 调用用于生成AOP的代理对象的BeanPostProcessor,如果bean不为null,则说明产生代理对象了,可以直接返回Object bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null) {// 如果bean不为null ,则直接返回,这种情况通常为AOP创建了代理对象。后面的doCreateBean不再执行return bean;}}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,"BeanPostProcessor before instantiation of bean failed", ex);}try {// 正常的,非代理bean对象的创建// 包括检查是否进行了类加载(没有则进行类加载),bean对象实例创建,bean对象实例的属性赋值,init-method的调用,BeanPostProcessor的调用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);}
    }
    
  • doCreateBean方法定义一个完整bean对象的创建,在内部完成bean对象后置处理器BeanPostProcessor的调用,初始化相关的init-methdo和InitializingBean的afterPropertiesSet的调用:

    // bean对象实例创建的核心实现方法
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// 使用构造函数或者工厂方法来创建bean对象实例// Instantiate the bean.BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);}final Object bean = instanceWrapper.getWrappedInstance();Class<?> beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// 修改BeanDefinition的BeanPostProcessor的执行,如合并其他BeanDefinition进来// Allow post-processors to modify the merged bean definition.synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {// 调用修改BeanDefinition的BeanPostProcessor,// 即MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinitionapplyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}mbd.postProcessed = true;}}...// 初始化bean对象实例,包括属性赋值,初始化方法,BeanPostProcessor的执行// Initialize the bean instance.Object exposedObject = bean;try {// 1. InstantiationAwareBeanPostProcessor执行:// 	(1). 调用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation,//  (2). 调用InstantiationAwareBeanPostProcessor的postProcessProperties和postProcessPropertyValues// 2. bean对象的属性赋值populateBean(beanName, mbd, instanceWrapper);// 1. Aware接口的方法调用// 2. BeanPostProcess执行:调用BeanPostProcessor的postProcessBeforeInitialization// 3. 调用init-method:首先InitializingBean的afterPropertiesSet,然后应用配置的init-method// 4. BeanPostProcess执行:调用BeanPostProcessor的postProcessAfterInitializationexposedObject = initializeBean(beanName, exposedObject, mbd);}...// Register bean as disposable.try {registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}return exposedObject;
    }
    

3. FactoryBean创建的bean对象

  • FactoryBean接口在其getObject方法自定义bean对象的创建过程,而不是使用以上的createBean方法,故应用中配置的BeanPostProcessor,InitializingBean接口的方法等不会对FactoryBean创建的bean对象起作用。
  • 这样设计也保证了spring自身可以利用FactoryBean接口来创建bean对象,如内部组件,而不会受到应用代码的影响。

4. bean对象注册到IOC容器

a. 单例bean对象
  • 单例bean对象注册到IOC容器是在doGetBean方法内完成的,核心逻辑为getSingleton:调用createBean方法创建bean对象实例然后注册到单例bean对象映射map中。

    // Create bean instance.
    if (mbd.isSingleton()) {// 创建bean对象实例并注册到单例bean映射map中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;}});// 如果sharedInstance不是FactoryBean接口的实现类,则直接返回sharedInstance;// 否则调用sharedInstance的getObject方法获取实际的bean对象bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    }
    
  • 在getSingleton方法内调用addSingleton方法将该bean对象存放到单例bean对象映射map,即singletonObjects:

    protected void addSingleton(String beanName, Object singletonObject) {synchronized (this.singletonObjects) {this.singletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);this.earlySingletonObjects.remove(beanName);this.registeredSingletons.add(beanName);}
    }
    
b. FactoryBean创建的bean对象
  • FactoryBean创建的bean对象,即调用FactoryBean的getObject方法返回的bean对象,注册到IOC容器(由FactoryBean创建的bean对象的映射map,即FactoryBeanRegistrySupport的factoryBeanObjectCache),也是在doGetBean方法中实现的,具体在FactoryBeanRegistrySupport的getObjectForBeanInstance方法实现。

这篇关于Spring IOC源码分析(七):IOC容器的对象存储体系与bean对象的加载流程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/957102

相关文章

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java进程异常故障定位及排查过程

《Java进程异常故障定位及排查过程》:本文主要介绍Java进程异常故障定位及排查过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、故障发现与初步判断1. 监控系统告警2. 日志初步分析二、核心排查工具与步骤1. 进程状态检查2. CPU 飙升问题3. 内存

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os

java中新生代和老生代的关系说明

《java中新生代和老生代的关系说明》:本文主要介绍java中新生代和老生代的关系说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、内存区域划分新生代老年代二、对象生命周期与晋升流程三、新生代与老年代的协作机制1. 跨代引用处理2. 动态年龄判定3. 空间分

Java设计模式---迭代器模式(Iterator)解读

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录1、迭代器(Iterator)1.1、结构1.2、常用方法1.3、本质1、解耦集合与遍历逻辑2、统一

Java内存分配与JVM参数详解(推荐)

《Java内存分配与JVM参数详解(推荐)》本文详解JVM内存结构与参数调整,涵盖堆分代、元空间、GC选择及优化策略,帮助开发者提升性能、避免内存泄漏,本文给大家介绍Java内存分配与JVM参数详解,... 目录引言JVM内存结构JVM参数概述堆内存分配年轻代与老年代调整堆内存大小调整年轻代与老年代比例元空

深度解析Java DTO(最新推荐)

《深度解析JavaDTO(最新推荐)》DTO(DataTransferObject)是一种用于在不同层(如Controller层、Service层)之间传输数据的对象设计模式,其核心目的是封装数据,... 目录一、什么是DTO?DTO的核心特点:二、为什么需要DTO?(对比Entity)三、实际应用场景解析

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

从原理到实战深入理解Java 断言assert

《从原理到实战深入理解Java断言assert》本文深入解析Java断言机制,涵盖语法、工作原理、启用方式及与异常的区别,推荐用于开发阶段的条件检查与状态验证,并强调生产环境应使用参数验证工具类替代... 目录深入理解 Java 断言(assert):从原理到实战引言:为什么需要断言?一、断言基础1.1 语