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

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

自动装配概念

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

前提条件

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

<dependencies>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter</artifactId>
     </dependency>

     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
     </dependency>
     
     <dependency>
		 <groupId>org.mybatis.spring.boot</groupId>
		 <artifactId>mybatis-spring-boot-starter</artifactId>
	 </dependency>  
	 
 </dependencies>

以 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<Interceptor[]> interceptorsProvider, ResourceLoader resourceLoader, ObjectProvider<DatabaseIdProvider> 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);
    }
}

org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration 位置如下:

① 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(实现 BeanFactoryPostProcessor 接口) 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<ConfigurationClass, ConfigurationClass> configurationClasses 属性 :

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

⑤ bean 注册与实例化

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

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值