实现springboot的starter

x33g5p2x  于2021-12-13 转载在 Spring  
字(6.2k)|赞(0)|评价(0)|浏览(208)

什么是 Spring Boot

Spring Boot 基本上是 Spring 框架的扩展,它消除了设置 Spring 应用程序所需的复杂例行配置。我们在使用 Spring 框架的时候,我们接触得比较多的应该是 Spring MVC、 IOC 、 DI 、AOP 等等,而这些框架在使用的过程中会需要配置大量的 XML,或者需要做很多繁琐的配置。Spring Boot 可以帮助我们快速搭建一个基于 Spirng 框架以及 Spring 生态体系的应用解决方案。

  • 创建独立的 Spring 应用程序
  • 直接嵌入 Tomcat,Jetty 或 Undertow(无需部署 WAR 文件),java -jar 就可以运行
  • 提供 starter 依赖来简化你自己的配置
  • 自动装配 Spring 和第三方的依赖
  • 提供可用于生产的功能,例如指标,运行状况检查和外部化配置,比如 Actuator
  • 完全没有代码生成,也不需要 XML 配置

约定大于配置

  • maven 的目录结构,默认有 resources 文件夹存放配置文件,默认打包方式为 jar
  • spring-boot-starter-web 中默认包含 spring mvc 相关依赖以及内置的 tomcat 容器,使得构建一个 web 应用更加简单
  • 默认提供 application.properties/yml 文件
  • 默认通过 spring.profiles.active 属性来决定运行环境时读取的配置文件
  • EnableAutoConfiguration 默认对于依赖的 starter 进行自动装配

自动装配

@SpringBootApplication实际上是一个复合注解,主要由以下构成:

@Configuration

@Configuration是 JavaConfig 形式的基于 Spring IOC 容器的配置类使用的一种注解。所以在启动类里面标注了 @Configuration,意味着它其实也是一个 IoC 容器的配置类。

传统意义上的 Spring 应用都是基于 xml 形式来配置 bean 的依赖关系。但是从 Spring3 开始,Spring 就支持了两种 bean 的配置方式,一种是基于 xml 文件方式,另一种就是 JavaConfig,任何一个标注了 @Configuration 的 Java 类定义都是一个 JavaConfig 配置类。而在这个配置类中,任何标注了 @Bean 的方法,它的返回值都会作为 Bean 定义注册到 Spring 的 IoC 容器,方法名默认成为这个 Bean 的 id。然后通过 spring 容器在启动的时候,把 Bean 进行初始化并且,如果 Bean 之间存在依赖关系,则分析这些已经在 IoC 容器中的 Bean 根据依赖关系进行组装。

@ComponentScan

@ComponentScan 就是扫包,相当于 xml 配置文件中的context:component-scan 。

它的主要作用就是扫描指定路径下的标识了需要装配的类,自 动装配到 Spring 的 IoC 容器中。

标识需要装配的类的形式主要是:@Component、@Repository、@Service、@Controller 这类的注解标识的类。(注:@Repository、@Service、@Controller 的底层还是 @Component)。ComponentScan 默认会扫描当前 package 下的的所有加了相关注解标识的类到 IoC 容器中。

@EnableAutoConfiguration

@EnableAutoConfiguration 是 Spring Boot 的灵魂。从 Spring3.1 开始,提供了一系列的 @Enable 开头的注解,它是在 JavaConfig 框架上更进一步的完善,使用户在使用 Spring 相关的框架避免配置大量的代码从而降低使用的难度。

每一个涉及到 Enable 开头的注解,都会带有一个 @Import 的注解, @EnableAutoConfiguration 也不例外。

@Import 对应 XML 形式下的 ,就是导入资源,把多个分布在不同容器下的配置合并在一个配置中。@Import 注解可以配置三种不同的 class :

普通 Bean 或者带有 @Configuration 的配置文件

实现 ImportSelector 接口进行动态注入

实现 ImportBeanDefinitionRegistrar 接口进行动态注入

这里导入的是第二种 importSelector,这是一种动态注入 Bean 的技术。其中AutoConfigurationImportSelector实现了 ImportSelector 接口。借助AutoConfigurationImportSelector,@EnableAutoConfiguration帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器。

在AutoConfigurationImportSelector类中可以看到通过 SpringFactoriesLoader.loadFactoryNames()把 spring-boot-autoconfigure.jar/META-INF/spring.factories中每一个xxxAutoConfiguration文件都加载到容器中,spring.factories文件里每一个xxxAutoConfiguration文件一般都会有下面的条件注解:

  • @ConditionalOnClass : classpath中存在该类时起效
  • @ConditionalOnMissingClass : classpath中不存在该类时起效
  • @ConditionalOnBean : DI容器中存在该类型Bean时起效
  • @ConditionalOnMissingBean : DI容器中不存在该类型Bean时起效
  • @ConditionalOnSingleCandidate : DI容器中该类型Bean只有一个或@Primary的只有一个时起效
  • @ConditionalOnExpression : SpEL表达式结果为true时
  • @ConditionalOnProperty : 参数设置或者值一致时起效
  • @ConditionalOnResource : 指定的文件存在时起效
  • @ConditionalOnJndi : 指定的JNDI存在时起效
  • @ConditionalOnJava : 指定的Java版本存在时起效
  • @ConditionalOnWebApplication : Web应用环境下起效
  • @ConditionalOnNotWebApplication : 非Web应用环境下起效

SpringFactoriesLoader

SpringFactoriesLoader属于Spring框架私有的一种扩展方案(类似于Java的SPI方案java.util.ServiceLoader),其主要功能就是从指定的配置文件META-INF/spring-factories加载配置,spring-factories是一个典型的java properties文件,只不过Key和Value都是Java类型的完整类名。

对于@EnableAutoConfiguration来说,SpringFactoriesLoader的用途稍微不同一些,其本意是为了提供SPI扩展的场景,而在@EnableAutoConfiguration场景中,它更多提供了一种配置查找的功能支持,即根据@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfig.EnableAutoConfiguration作为查找的Key,获得对应的一组@Configuration类。

SpringFactoriesLoader是一个抽象类,类中定义的静态属性定义了其加载资源的路径public static final String FACTORIES_RESOURCE_LOCATION = “META-INF/spring.factories”,此外还有三个静态方法:

  • loadFactories:加载指定的factoryClass并进行实例化。
  • loadFactoryNames:加载指定的factoryClass的名称集合。
  • instantiateFactory:对指定的factoryClass进行实例化。

loadFactories方法首先获取类加载器,然后调用loadFactoryNames方法获取所有的指定资源的名称集合、接着调用instantiateFactory方法实例化这些资源类并将其添加到result集合中。最后调用AnnotationAwareOrderComparator.sort方法进行集合的排序。

SpringBoot starter

SpringBoot中的starter是一种非常重要的机制,能够抛弃以前繁杂的配置,将其统一集成进starter,应用者只需要在maven中引入starter依赖,SpringBoot就能自动扫描到要加载的信息并启动相应的默认配置。

starter让我们摆脱了各种依赖库的处理,需要配置各种信息的困扰。SpringBoot会自动通过classpath路径下的类发现需要的Bean,并注册进IOC容器。SpringBoot提供了针对日常企业应用研发各种场景的spring-boot-starter依赖模块。所有这些依赖模块都遵循着约定成俗的默认配置,并允许我们调整这些配置,即遵循“约定大于配置”的理念。

starter的实现方法

  1. 创建一个starter项目,Spring 官方定义的 starter 通常命名遵循的格式为 spring-boot-starter-{name}。
  2. 创建一个ConfigurationProperties用于保存你的配置信息。
  3. 创建一个AutoConfiguration,引用定义好的配置信息。在AutoConfiguration中实现所有starter应该完成的操作,并且把这个类加入spring.factories配置文件中进行声明。
  4. 打包项目,之后在一个SpringBoot项目中引入该项目依赖。

引入的依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-autoconfigure</artifactId>
    </dependency>
</dependencies>
   <build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
           </plugin>
       </plugins>
   </build>

spring-boot-autoconfigure中包含大量核心注解,包含条件注解等。

创建properties属性类,用于读取属性

@ConfigurationProperties(prefix = "com.test")
public class TestServiceProperties {

    private String name = "test";

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

@ConfigurationProperties配置此注解可以自动导入application.properties配置文件中的属性,前提需要指定属性前缀prefix。如果application.properties文件中未指定相应属性,便使用默认的,如上name=“test”。

创建配置类

public class TestServiceConfiguration {

    private String name;

    public String getName() {
        return "name is " + name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

创建自动配置类

@Configuration
@EnableConfigurationProperties(TestServiceProperties.class)
@ConditionalOnClass(TestServiceConfiguration.class)
@ConditionalOnProperty(prefix = "com.test", value = "enabled", matchIfMissing = true)
public class TestServiceAutoConfiguration {

    @Autowired
    private TestServiceProperties testServiceProperties;

    @Bean
    @ConditionalOnMissingBean(TestServiceConfiguration.class)
    public TestServiceConfiguration testServiceConfiguration() {
        TestServiceConfiguration testService = new TestServiceConfiguration();
        TestService.setName(testServiceProperties.getName());
        return testService;
    }
}
  • @Configuration:表明此类是一个配置类,将变为一个bean被spring进行管理。
  • @EnableConfigurationProperties:启用属性配置,将读取TestServiceProperties里面的属性。
  • @ConditionalOnClass:当类路径下面有TestServiceConfiguration此类时,自动配置。
  • @ConditionalOnProperty:判断指定的属性是否具备指定的值。
  • @ConditionalOnMissingBean:当容器中没有指定bean时,创建此bean。

配置类注册

在resources文件夹下面新建一个META-INF文件,并在下面创建spring.factories文件,将配置类进行注册。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
 com.test.TestServiceAutoConfiguration

使用

自定义的starter编写完毕,执行mvn clean install将项目打成一个jar包。新建一个springboot项目,在pom文件中添加刚刚打包的jar。

在application.properties添加

com.test.name=test

相关文章