我是靠谱客的博主 难过雪碧,最近开发中收集的这篇文章主要介绍SpringBoot自动装配原理与自己写一个starter前言一、自己定义一个@EnableConfiguration和ImportSelector,实现自动装配二、自动装配原理三、SPI四、自己构建一个starter组件,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言

SpringBoot之所以可以做到简化配置文件直接启动,无外乎是其内部的两种设计策略:开箱即用和约定大于配置

开箱即用:在开发过程中,通过maven项目的pom文件中添加相关依赖包,然后通过相应的注解来代替繁琐的XML配置以管理对象的生命周期。

约定大于配置:由SpringBoot本身来配置目标结构,由开发者在结构中添加信息的软件设计范式。这一特点虽降低了部分灵活性,增加了BUG定位的复杂性,但减少了开发人员需要做出决定的数量,同时减少了大量的XML配置,并且可以将代码编译、测试和打包等工作自动化。

一、自己定义一个@EnableConfiguration和ImportSelector,实现自动装配

需要一下几个步骤(此实践基于xx课程):

  1. 定义RedisConfiguration类,用@Configuration标注方法,并在用@Bean标注的方法,返回bean实例
  2. 自定义@EnableConfiguration注解
  3. 自定义GpDefineImportSelector类,实现ImportSelector接口,并重写selectImports方法,selectImports方法里返回我们需要自动装配的RedisConfiguration等类的全路径字符串数组
  4. 将自定义的@EnableConfiguration注解,放到启动类上

具体代码如下:

1.1 RedisConfiguration.class

@Configuration
public class RedisConfiguration {

    @Bean
    public GpRedisTemplate gpRedisTemplate(){
        return new GpRedisTemplate();
    }
}

1.2 自定义@EnableConfiguration注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(GpDefineImportSelector.class)
public @interface EnableConfiguration {

}

1.3 自定义GpDefineImportSelector类

public class GpDefineImportSelector implements ImportSelector{
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //动态导入bean, 告诉了Spring  , 两个配置类在哪里

        //TODO 在这里去加载所有的配置类就行?
        // 通过某种机制去完成指定路径的配置类的扫描就行?
        //package.class.classname
        return new String[]{GpSqlSessionFactory.class.getName(), RedisConfiguration.class.getName()};
    }
}

1.4 将自定义的@EnableConfiguration注解,放到启动类上

这样GpRedisTemplate.class的对象就可以自动装配到spring容器中了。

二、自动装配原理

2.1 @SpringBootApplication注解

先看看Springboot主配置类上的@SpringBootApplication注解:

如上图, @SpringBootApplication其实是包含了三个主要的注解:

  1. @SpringBootConfiguration
  2. @EnableAutoConfiguration
  3. @ComponentScan

2.1.1 @SpringBootConfiguration

首先看@SpringBootConfiguration注解:

这个注解很简单,表名该类是一个Spring的配置类。 

2.1.2 @EnableAutoConfiguration

 该注解包含两个重要的注解:

  1. @AutoConfigurationPackage
  2. @Import(EnableAutoConfigurationImportSelector.class)

 2.1.2.1 @AutoConfigurationPackage

 这个注解是自动配置包,主要是使用的@Import来给Spring容器中导入一个组件 ,这里导入的是Registrar.class。

来看下这个Registrar:

我们打个断点看一下:

它的包路径是什么呢?——就是我们主配置类同级目录的包:

 那么metadata是什么呢:
它就是我们的主配置类——MyProjectMyProjectApplication类:

由上面我们可以推测:就是将主配置类(即@SpringBootApplication标注的类)所在包及子包里面所有组件扫描加载到Spring容器。

现在包扫描路径获取到了,那具体加载哪些组件呢,看看下面这个注解。

2.1.2.2 @Import(EnableAutoConfigurationImportSelector.class)

 @Import注解就是给Spring容器中导入一些组件,这里传入了一个组件的选择器:EnableAutoConfigurationImportSelector.class。

它有一个实现其他类的selectImports方法,这个方法的本质是:将所有需要导入的组件以全类名的方式返回;

有了自动配置类,免去了我们手动编写配置注入功能组件等的工作。
那他是如何获取到这些配置类的呢,看看上面这个方法:

它会给容器导入很多的配置类(通常由第三方实现,类名是xxxAutoConfiguration);就是给容器中导入这个场景需要的所有组件,并配置好这些组件: 

通过debug,我们继续探究:

 

Spring Boot在启动的时候从类路径下的META-INF/spring.factories中获取key为EnableAutoConfiguration(实际上是EnableAutoConfiguration的全路径明)指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作。

以druid-spring-boot-starter为例,我们看一下spring.factories:

 

由上我们可以得出结论:

当我们的SpringBoot项目启动的时候,会先导入AutoConfigurationImportSelector,这个类会帮我们选择所有候选的配置,我们需要导入的配置都是SpringBoot帮我们写好的一个一个的配置类,那么这些配置类的位置,存在与META-INF/spring.factories文件中,通过这个文件,Spring可以找到这些配置类的位置,于是去加载其中的配置。

拓展:spring.factories中存在那么多的配置,每次启动时都是把它们全量加载吗?这显然是不现实的。

这其实也是我在看源码的时候存在疑问的地方,因为其中有一个注解并不常用,我们点开一个配置类就可以看到。

@ConditionalOnXXX:如果其中的条件都满足,该类才会生效。

所以在加载自动配置类的时候,并不是将spring.factories的配置全量加载进来,而是通过这个注解的判断,如果注解中的类都存在,才会进行加载。

 2.3 @ComponentScan

ComponentScan这个注解是大家接触得最多的了,相当于xml配置文件中的<context:component-scan>。 它的主要作用就是扫描指定路径下的标识了需要装配的类,自动装配到spring的Ioc容器中。

标识需要装配的类的形式主要是:@Component、@Repository、@Service、@Controller这类的注解标识的类。

所以上图需要加一块@ConditionOnClass判断:

三、SPI

之前有文章讲过SPI,可以看看:dubbo内核简介(附部分源码解读)

四、自己构建一个starter组件

之前也有文章逐步讲解并实践过:年轻人的第一个自定义Springboot starter

在上面我写的starter时,我没有用到下面两个注解,但在很多时候,可能会用到下面两个注解:

  • @ConditionalOnClass(xx.class)
  • @EnableConfigurationProperties(xxProperties.class)-上面的例子用到了

 4.1 @ConditionalOnClass

在这里插入图片描述

 4.2 @EnableConfigurationProperties

作用:@ConfigurationProperties 注解的类生效

        如果一个配置类只配置@ConfigurationProperties注解,而没有使用@Component,那么在IOC容器中是获取不到properties 配置文件转化的bean。说白了 @EnableConfigurationProperties 相当于把使用 @ConfigurationProperties 的类进行了一次注入。

关于这个注解,具体可以查看上面的链接例子。

最后

以上就是难过雪碧为你收集整理的SpringBoot自动装配原理与自己写一个starter前言一、自己定义一个@EnableConfiguration和ImportSelector,实现自动装配二、自动装配原理三、SPI四、自己构建一个starter组件的全部内容,希望文章能够帮你解决SpringBoot自动装配原理与自己写一个starter前言一、自己定义一个@EnableConfiguration和ImportSelector,实现自动装配二、自动装配原理三、SPI四、自己构建一个starter组件所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(62)

评论列表共有 0 条评论

立即
投稿
返回
顶部