IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> spring核心之Bean加载过程剖析 -> 正文阅读

[Java知识库]spring核心之Bean加载过程剖析

前言:

此文是从spring框架的源码进行剖析Bean加载的一个过程,请耐心一步一步阅读

目前来说,我们一般开发都是基于SpringBoot进行,所以我们就从SpringBoot项目启动类开始解析


启动入口:

先从加载bean对象的角度来看一下springboot程序启动类

@SpringBootApplication //负责加载其他starter依赖的Bean信息
public class YosmfaApplication {

    public static void main(String[] args) {
        //负责加载本地项目的所有Bean信息
        SpringApplication.run(YosmfaApplication.class, args);
    }

}

@SpringBootApplication注解加载其他starter的解读请参考springboot如何实现自动装配

这里详细的解析下springboot程序加载本地项目中的Bean信息到Ioc容器的过程
1、进入SpringApplication.run方法
在这里插入图片描述
找到this.refreshContext(),它会调用spring框架下org.springframework.context.support.AbstractApplicationContext#refresh()方法,该refresh()方法就是spring框架用来加载本地项目中所有的bean信息的。主要的Bean对象的加载过程都是在这个方法逻辑里调用的

这里要说一个点,通常我们一般说Bean加载,Bean加载。实际在Spring框架里,只是一个刷新容器的概念,只不过刷新容器的时候把你配置的Bean信息加载到容器当中,所以在Spring源码里是一个refresh()方法

public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            //准备初始化BeanFactory
            StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
            this.prepareRefresh();
//核心逻辑点:初始化beanFactory,同时会加载项目中所有的配置Bean信息封装成BeanDefinition
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
//一般逻辑点:初始化ApplicationContextAwareProcessor对象,该对象会在Bean创建且填充完属性后调用一些Aware扩展逻辑
            this.prepareBeanFactory(beanFactory);

            try {
//beanFactory创建后置方法,属于扩展方法,无实现。Spring特地留给你们重写的扩展方法,但Springboot对其进行了一个重写
                this.postProcessBeanFactory(beanFactory);
                StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
//见名猜其意,调用一些BeanFactory后置处理逻辑
                this.invokeBeanFactoryPostProcessors(beanFactory);
//将一些Bean创建后的一些后置处理类添加到BeanFactory,后续创建完Bean对象后会调用
                this.registerBeanPostProcessors(beanFactory);
                beanPostProcess.end();
                //不重要
                this.initMessageSource();
                //不重要
                this.initApplicationEventMulticaster();
                //扩展接口,Spring留给你们重写的
                this.onRefresh();
                //添加一些监听器,不是重点
                this.registerListeners();
//核心逻辑:根据上面初始化时加载的BeanDefinition创建Bean实例,创建完后会进行属性填充
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var10) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
                }

                this.destroyBeans();
                this.cancelRefresh(var10);
                throw var10;
            } finally {
                this.resetCommonCaches();
                contextRefresh.end();
            }

        }
    }

上面的解析中,有两个核心逻辑点需要关注

加载BeanDefinitions

BeanFactory初始化后会扫描项目中所有的Bean配置信息加载成BeanDefinition对象

 ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();

从this.obtainFreshBeanFactory()方法一直跟下来,发现加载Bean信息的实现有下面几种。
在这里插入图片描述
SpringBoot是采用AnnotationConfigWebApplicationContext的实现,也就是扫描注解的方式加载Bean信息。而现在常用的一般也都是注解方式。

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
        AnnotatedBeanDefinitionReader reader = this.getAnnotatedBeanDefinitionReader(beanFactory);
        ClassPathBeanDefinitionScanner scanner = this.getClassPathBeanDefinitionScanner(beanFactory);
        BeanNameGenerator beanNameGenerator = this.getBeanNameGenerator();
        if (beanNameGenerator != null) {
            reader.setBeanNameGenerator(beanNameGenerator);
            scanner.setBeanNameGenerator(beanNameGenerator);
            beanFactory.registerSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator", beanNameGenerator);
        }

        ScopeMetadataResolver scopeMetadataResolver = this.getScopeMetadataResolver();
        if (scopeMetadataResolver != null) {
            reader.setScopeMetadataResolver(scopeMetadataResolver);
            scanner.setScopeMetadataResolver(scopeMetadataResolver);
        }

        if (!this.componentClasses.isEmpty()) {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Registering component classes: [" + StringUtils.collectionToCommaDelimitedString(this.componentClasses) + "]");
            }

            reader.register(ClassUtils.toClassArray(this.componentClasses));
        }

        if (!this.basePackages.isEmpty()) {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Scanning base packages: [" + StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");
            }

            scanner.scan(StringUtils.toStringArray(this.basePackages));
        }

        String[] configLocations = this.getConfigLocations();
        if (configLocations != null) {
            String[] var7 = configLocations;
            int var8 = configLocations.length;

            for(int var9 = 0; var9 < var8; ++var9) {
                String configLocation = var7[var9];

                try {
                    Class<?> clazz = ClassUtils.forName(configLocation, this.getClassLoader());
                    if (this.logger.isTraceEnabled()) {
                        this.logger.trace("Registering [" + configLocation + "]");
                    }

                    reader.register(new Class[]{clazz});
                } catch (ClassNotFoundException var13) {
                    if (this.logger.isTraceEnabled()) {
                        this.logger.trace("Could not load class for config location [" + configLocation + "] - trying package scan. " + var13);
                    }

                    int count = scanner.scan(new String[]{configLocation});
                    if (count == 0 && this.logger.isDebugEnabled()) {
                        this.logger.debug("No component classes found for specified class/package [" + configLocation + "]");
                    }
                }
            }
        }

    }

具体的解析逻辑可以自己debug看,大概就是加载项目下所有的注解配置Bean信息。

创建Bean实例

此方法会根据上面加载的Bean信息创建Bean实例,填充字段属性,处理一些Bean的后置处理逻辑postProcess

this.finishBeanFactoryInitialization(beanFactory);

跟进去后,核心方法调用如下:

 protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        if (beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
            beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));
        }

        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver((strVal) -> {
                return this.getEnvironment().resolvePlaceholders(strVal);
            });
        }

        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        String[] var3 = weaverAwareNames;
        int var4 = weaverAwareNames.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            String weaverAwareName = var3[var5];
            this.getBean(weaverAwareName);
        }

        beanFactory.setTempClassLoader((ClassLoader)null);
        beanFactory.freezeConfiguration();
//核心调用,可直接进入此方法查看
        beanFactory.preInstantiateSingletons();
    }

进入beanFactory.preInstantiateSingletons()方法,此方法是抽象方法,由DefaultListableBeanFactory类实现。
在这里插入图片描述
下面开始分析preInstantiateSingletons创建Bean实例的逻辑,此方法核心调用就是一个 getBean() 方法

public void preInstantiateSingletons() throws BeansException {
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Pre-instantiating singletons in " + this);
        }

        List<String> beanNames = new ArrayList(this.beanDefinitionNames);
        //取出之前加载的Bean信息,遍历进行创建
        Iterator var2 = beanNames.iterator();

        while(true) {
            String beanName;
            Object bean;
            do {
                while(true) {
                    RootBeanDefinition bd;
                    do {
                        do {
                            do {
                                if (!var2.hasNext()) {
                                    var2 = beanNames.iterator();

                                    while(var2.hasNext()) {
                                        beanName = (String)var2.next();
                                        Object singletonInstance = this.getSingleton(beanName);
                                        if (singletonInstance instanceof SmartInitializingSingleton) {
                                            StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize").tag("beanName", beanName);
                                            SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
                                            if (System.getSecurityManager() != null) {
                                                AccessController.doPrivileged(() -> {
                                                    smartSingleton.afterSingletonsInstantiated();
                                                    return null;
                                                }, this.getAccessControlContext());
                                            } else {
                                                smartSingleton.afterSingletonsInstantiated();
                                            }

                                            smartInitialize.end();
                                        }
                                    }

                                    return;
                                }

                                beanName = (String)var2.next();
                                bd = this.getMergedLocalBeanDefinition(beanName);
                            } while(bd.isAbstract());
                        } while(!bd.isSingleton());
                    } while(bd.isLazyInit());

                    if (this.isFactoryBean(beanName)) {
                        //核心调用
                        bean = this.getBean("&" + beanName);
                        break;
                    }
                    //核心调用
                    this.getBean(beanName);
                }
            } while(!(bean instanceof FactoryBean));

            FactoryBean<?> factory = (FactoryBean)bean;
            boolean isEagerInit;
            if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                SmartFactoryBean var10000 = (SmartFactoryBean)factory;
                ((SmartFactoryBean)factory).getClass();
                isEagerInit = (Boolean)AccessController.doPrivileged(var10000::isEagerInit, this.getAccessControlContext());
            } else {
                isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit();
            }

            if (isEagerInit) {
               //核心调用
                this.getBean(beanName);
            }
        }
    }

继续跟进 getBean() 方法,进入到org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean()方法
调用该方法会去ioc容器中获取bean实例,如果没有则会创建Bean实例(前提是BeanFactory中有BeanDefinition信息)


 Object sharedInstance = this.getSingleton(beanName);
 //从ioc容器中取对象,具体ioc容器是一个三级缓存,简单来说就是三个map,取得时候一个map一个map取,这里不是本文重点,只做简单介绍。具体可自行了解Spring三级缓存

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                synchronized(this.singletonObjects) {
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        singletonObject = this.earlySingletonObjects.get(beanName);
                        if (singletonObject == null) {
                            ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                            if (singletonFactory != null) {
                                singletonObject = singletonFactory.getObject();
                                this.earlySingletonObjects.put(beanName, singletonObject);
                                this.singletonFactories.remove(beanName);
                            }
                        }
                    }
                }
            }
        }

        return singletonObject;
    }

如ioc容器中获取不到Bean对象,则会调用this.createBean() 方法创建
在这里插入图片描述
继续跟进createBean() 方法,它的核心调用是this.doCreateBean
在这里插入图片描述
真正创建bean实例以及属性赋值的逻辑都在这个方法里,进入doCreateBean方法查看

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }

        if (instanceWrapper == null) {
           //通过反射获取构造方法调用创建对象实例
           //这里反射获取的class是spring创建的代理类class
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }

        Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        synchronized(mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                } catch (Throwable var17) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
                }

                mbd.postProcessed = true;
            }
        }

        boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
        if (earlySingletonExposure) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
            }

            this.addSingletonFactory(beanName, () -> {
                return this.getEarlyBeanReference(beanName, mbd, bean);
            });
        }

        Object exposedObject = bean;

        try {
        //填充属性-字段属性赋值
            this.populateBean(beanName, mbd, instanceWrapper);
        //ApplicationContextAwareProcessor,一些aware的处理
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        } catch (Throwable var18) {
            if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
                throw (BeanCreationException)var18;
            }

            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
        }

        if (earlySingletonExposure) {
            Object earlySingletonReference = this.getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
                    String[] dependentBeans = this.getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                    String[] var12 = dependentBeans;
                    int var13 = dependentBeans.length;

                    for(int var14 = 0; var14 < var13; ++var14) {
                        String dependentBean = var12[var14];
                        if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }

                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

        try {
            this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
            return exposedObject;
        } catch (BeanDefinitionValidationException var16) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
        }
    }

上面需重点关注的逻辑点有三个地方
1、创建bean实例

//通过反射获取构造方法调用创建对象实例
//这里反射获取的class是spring创建的代理类class
 instanceWrapper = this.createBeanInstance(beanName, mbd, args);

2、属性填充-赋值

 this.populateBean(beanName, mbd, instanceWrapper);

3、一些aware扩展的处理

 exposedObject = this.initializeBean(beanName, exposedObject, mbd);

处理完方法后会返回创建的bean实例

结束

到这,整个spring加载bean对象的一个过程就完成了。
总结来讲,先是:org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory()方法初始化BeanFactory并拿到本地项目中所有配置的BeanDefinitions信息,而后org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons()方法根据遍历BeanDefinitions信息创建相应的Bean实例,实际的bean创建逻辑则是在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean()方法当中

纸上得来终觉浅,大家可以自己debug跟进一下整个bean的加载过程。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-04-06 16:04:04  更:2022-04-06 16:04:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:56:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码