栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot源码解析(1.4)-自动装配原理(总结)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot源码解析(1.4)-自动装配原理(总结)

SpringBoot源码解析(1.4)-自动装配原理(总结) 自动装配概念

https://blog.csdn.net/sql2008help/article/details/123251638

前提条件

引入 SpringBoot 启动依赖,比方进行web开发需要引入web依赖,需要使用 mybatis 引入mybatis 依赖,这种启动依赖不仅可以简化原来依赖方式,还会引入autoconfig 依赖,SpringBoot 就是结合 AutoConfiguration 类帮我们初始化默认环境的。


     
         org.springframework.boot
         spring-boot-starter
     

     
         org.springframework.boot
         spring-boot-starter-web
     
     
     
		 org.mybatis.spring.boot
		 mybatis-spring-boot-starter
	   
	 
 

以 mybatis 为例,mybatis-spring-boot-starter 依赖就包含了 mybatis 和 mybatis-spring 依赖,不需要像原来SSM开发模式一样 在pom.xml 中定义多个依赖,并且在 MybatisAutoConfiguration 类中会默认初始化一个 SqlSessionFactory ,不需要再自定义了

package org.mybatis.spring.boot.autoconfigure;

@Configuration
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@ConditionalOnBean({DataSource.class})
@EnableConfigurationProperties({MybatisProperties.class})
@AutoConfigureAfter({DataSourceAutoConfiguration.class})
public class MybatisAutoConfiguration {
    private static final Logger logger = LoggerFactory.getLogger(MybatisAutoConfiguration.class);
    private final MybatisProperties properties;
    private final Interceptor[] interceptors;
    private final ResourceLoader resourceLoader;
    private final DatabaseIdProvider databaseIdProvider;

    public MybatisAutoConfiguration(MybatisProperties properties, ObjectProvider interceptorsProvider, ResourceLoader resourceLoader, ObjectProvider databaseIdProvider) {
        this.properties = properties;
        this.interceptors = (Interceptor[])interceptorsProvider.getIfAvailable();
        this.resourceLoader = resourceLoader;
        this.databaseIdProvider = (DatabaseIdProvider)databaseIdProvider.getIfAvailable();
    }
    
    @Bean
    @ConditionalOnMissingBean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
        factory.setDataSource(dataSource);
        factory.setVfs(SpringBootVFS.class);
        if (StringUtils.hasText(this.properties.getConfigLocation())) {
            factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
        }
        。。。。。。。。
        factory.setConfiguration(this.properties.getConfiguration());
        。。。。。。。。
        return factory.getObject();
    }

    @Bean
    @ConditionalOnMissingBean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        ExecutorType executorType = this.properties.getExecutorType();
        return executorType != null ? new SqlSessionTemplate(sqlSessionFactory, executorType) : new SqlSessionTemplate(sqlSessionFactory);
    }
}

① SpringApplication 实例化

SpringBoot 启动类通过调用 SpringApplication.run 方法启动容器,在静态run方法中实际是调用的SpringApplication 实例的run方法,在 SpringApplication 实例化的过程中调用loadFactoryNames方法从meta-INF/spring.factories文件中读取配置并缓存至 SpringFactoriesLoader cache 中

org.springframework.core.io.support.SpringFactoriesLoader.loadFactoryNames

具体查看:https://blog.csdn.net/sql2008help/article/details/123253292

② AnnotationConfigServletWebServerApplicationContext 实例化

AnnotationConfigServletWebServerApplicationContext 类( 以下用 context 代替 )在 spring-boot 包下,它继承至 ServletWebServerApplicationContext (同样在spring-boot包中),而ServletWebServerApplicationContext 继承至 spring-web 包中的 GenericWebApplicationContext 类,类图如下:

context 是SpringBoot 的核心,它包含读取注解的工具 AnnotatedBeanDefinitionReader ( reader ) 、注册和生产bean实例的工厂 DefaultListableBeanFactory (beanFactory)等关键属性,在 context 初始化过程中(实际是 reader 初始化时)会往 beanFactory 注册 ConfigurationClassPostProcessor bean 定义

RootBeanDefinition  def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
// 往 DefaultListableBeanFactory 注册一个 key 为 org.springframework.context.annotation.internalConfigurationAnnotationProcessor,BeanDefinition 为 ConfigurationClassPostProcessor 的后置处理器
beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"));

具体查看:https://blog.csdn.net/sql2008help/article/details/123314453

③ AnnotationConfigServletWebServerApplicationContext refresh 方法

SpringApplication 在 run 方法中实例化 AnnotationConfigServletWebServerApplicationContext 后
开始调用 this.refreshContext(context); 方法,这个方法实际就是调用 context.refresh (父类org.springframework.context.support.AbstractApplicationContext refresh )方法

AbstractApplicationContext refresh 方法:

public void refresh() throws BeansException, IllegalStateException {
    synchronized(this.startupShutdownMonitor) {
        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
        this.prepareRefresh();
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
        // 填充 beanFactory 丰富 beanFactory 功能
        this.prepareBeanFactory(beanFactory);
        try {
            this.postProcessBeanFactory(beanFactory);
            StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
            // 执行 beanFactoryPostProcessors 对应方法
            this.invokeBeanFactoryPostProcessors(beanFactory);
            this.registerBeanPostProcessors(beanFactory);
            。。。。。。
            // 完成bean实例化
            this.finishBeanFactoryInitialization(beanFactory);
            this.finishRefresh();
        } catch (BeansException var10) {
           。。。。。。
            throw var10;
        } finally {
            this.resetCommonCaches();
            contextRefresh.end();
        }

    }
}

在 refresh 方法中重要的一个方法为:

this.invokeBeanFactoryPostProcessors(beanFactory);

这个方法接着调用 PostProcessorRegistrationDelegate 代理类的方法:

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors

在此方法中完成 ConfigurationClassPostProcessor 的实例化,并执行
ConfigurationClassPostProcessor 的 postProcessBeanDefinitionRegistry 方法,最终通过实例化出的 ConfigurationClassParser 对象完成启动类的解析

具体查看:https://blog.csdn.net/sql2008help/article/details/123354118

④ ConfigurationClassParser parse 方法 解析启动类

parser.parse(candidates); 解析启动类方法,该方法通过解析 @EnableAutoConfiguration 注解中 @import({AutoConfigurationimportSelector.class}) 获取 AutoConfigurationimportSelector 类,最终通过调用 AutoConfigurationimportSelector.AutoConfigurationGroup 类的 process 方法 读取 meta-INF/spring.factories 中 key 为 org.springframework.boot.autoconfigure.EnableAutoConfiguration 的类名列表得到需要自动装配的类名,并根据结果实例化成ConfigurationClass对象后填充到org.springframework.context.annotation.ConfigurationClassParser 对象 Map configurationClasses 属性 :

详情看:https://blog.csdn.net/sql2008help/article/details/123358545

⑤ bean 注册与实例化

自动装配的 bean 定义是在 AbstractApplicationContext refresh 方法中的 invokeBeanFactoryPostProcessors 方法里面完成的,具体代码为:
this.reader.loadBeanDefinitions(configClasses)

bean 实例化则是由 AbstractApplicationContext refresh 方法中的 finishBeanFactoryInitialization 方法完成

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/758974.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号