专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

Spring 是如何实例化 Bean 的?

Bean 的实例化_01

  在Spring中Bean的实例化是一个及其复杂的过程,从这篇文章开始,我就要学习容器初始化 refresh()方法中的 inishBeanFactoryInitialization(beanFactory);

finishBeanFactoryInitialization() 方法代码实现

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // Initialize conversion service for this context.
    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)); } // Register a default embedded value resolver if no bean post-processor // (such as a PropertyPlaceholderConfigurer bean) registered any before: // at this point, primarily for resolution in annotation attribute values. 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. /** * 冻结 所有的bean定义,说明注册的bean定义将不被修改或任何进一步的处理 */ beanFactory.freezeConfiguration(); // Instantiate all remaining (non-lazy-init) singletons. /** * 这里是重点代码 * 初始化剩下的实例(非惰性的) * 这个 预实例化的完成 委托给容器来实现,如果需要预实例化,采用getBean() 触发依赖注入, * 与正常的依赖注入的触发相比,只有触发的时间和场合不同,这里依赖注入是发生在容器执行 refresh() 的过程,也就是IOC容器初始化的过程 * 正常不是 Lazy-init 属性的依赖注入发生在IOC容器初始化完成之后,第一次向容器执行getBean() 时。 */ beanFactory.preInstantiateSingletons(); } 

  在上述的方法中,最重要的就是 preInstantiateSingletons()。这里我自己的理解就是预实例化容器之非懒加载(Lazy-init)的对象。

preInstantiateSingletons()

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. // 获取所有BeanDefinition的名字 List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... // 触发所有非延迟加载单例Bean的实例化 for (String beanName : beanNames) { // 合并父BeanDefinition RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); /** * 一个对象不是抽象的,并且是单例的,并且不是懒加载的 * 若这个对象不是一个FactoryBean,进入getBean()方法 */ if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { // 如果是FactoryBean 加上 & Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); 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 { /** * 调用容器中的 getBean() 方法 */ getBean(beanName); } } } // Trigger post-initialization callback for all applicable beans... for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { smartSingleton.afterSingletonsInstantiated(); return null; }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } } 

  从上述方法中可以看出,循环容器初始时添加到容器中的所有的 BeanName,然后根据 BeanName 获取到对应的 BeanDefinition。 通过 BeanDefinition中的属性来判断是否要触发相应的 getBean() 过程。   在 getBean() 之前,我首先要做的就是试着画一下对应的粗略流程图,后面的文章,将会一一的张开流程图里面的子流程。

121_1.png doGetBean流程图

  看完了整个流程图,下面就要开始第一个方法 getSingleton(String beanName) 的处理逻辑

getSingleton(String beanName)

public Object getSingleton(String beanName) {
    /** 参数true 设置标识允许早期依赖*/
    return getSingleton(beanName, true);
}

  调用重载的方法 getSingleton(String beanName, boolean allowEarlyReference) 来进行真正的逻辑处理,在Spring 中默认是允许 早期依赖的,也即 allowEarlyReferencetrue

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    //从Map中获取Bean,如果不为空直接返回,不在进行初始化工作
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        // 未被初始化 且 beanName 存在于正在被创建的单例Bean的池子中,进行初始化
 synchronized (this.singletonObjects) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { /** * 当某些方法需要提前初始化的时候会调用 * addSingletonFactory方法将对应的ObjectFactory初始化策略 * 存储在 singletonFactories中 */ ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { /** 调用预先设定的getObject()方法*/ singletonObject = singletonFactory.getObject(); /** * 记录在缓存中 * earlySingletonObjects 与 singletonFactories 互斥 */ this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; } 

在创建Bean的时候,首先,先到 singletonObjects 中获取,这对象是一个 Map,用来存放已经创建好的对象。里面的对象可以直接使用。   通过下面的图片来介绍上述 getSingleton() 的过程:

121_2.png 第一个getSingleton流程

  对于这个 getSingleton() 方法而言,在容器初始化的时候,singletonObjects 中必然没有对象,返回的结果则必然为null。

初识 三个Map

  在上述的三个方法中,我们将会看到有用到如下的三个 Map; private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); 这三个Map,在之后的依赖注入的处理中起着重要的作用。其中 singletonObjects 用于存放完全初始化好的bean;singletonFactories 用于存放 bean工厂对象; earlySingletonObjects 存放原始的bean对象。在Spring中定义了三个Map,缓存Spring容器中实例化的 Bean,并解决了注入过程 中循环依赖的问题。

标记Bean是已创建的

protected void markBeanAsCreated(String beanName) {
    // 没有创建
    if (!this.alreadyCreated.contains(beanName)) {
        // 通过 synchronized 保证只有一个线程创建
        synchronized (this.mergedBeanDefinitions) {
 // 再次检查 没有创建 if (!this.alreadyCreated.contains(beanName)) { // 从 mergedBeanDefinitions 中删除 beanName, // 并在下次访问时重新创建它 clearMergedBeanDefinition(beanName); // 添加到已创建bean 集合中 this.alreadyCreated.add(beanName); } } } } 

  容器初始化之处,这里我们自己的 Bean对应的 beanNamealreadyCreated 中必然是不存在的。因此,Spring在这里,就会将当前 的 BeanName 添加到 alreadyCreated 的集合中,用来标记当前的 Bean 是已创建的。这里为了保证添加一次,还采用了双重检测的方式。

本文使用 mdnice 排版

文章永久链接:https://tech.souyunku.com/28071

未经允许不得转载:搜云库技术团队 » Spring 是如何实例化 Bean 的?

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们