【Java入門】SpringBoot自動配置原理

作者:譚淼

一、運行原理

Spring Boot的運行是由註解@EnableAutoConfiguration提供的。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({EnableAutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
 
    Class<?>[] exclude() default {};
 
    String[] excludeName() default {};
}

這裏的關鍵功能是@Import註解。EnableAutoConfigurationImportSelector使用SpringFactoriesLoader.loadFactoryNames方法來掃描具有MEAT-INF/spring.factories文件的jar包(1.5版本以前使用EnableAutoConfigurationImportSelector類,1.5以後這個類廢棄了使用的是AutoConfigurationImportSelector類),下面是spring-boot-autoconfigure-1.5.4.RELEASE.jar下的MEAT-INF中的spring.factories文件的部分內容。

# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer
 
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer
 
# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
 
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnClassCondition
 
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\

裏面的類都是自動配置類,SpringBoot會根據這些自動配置類去自動配置環境。

下面我們就自動動手寫一個starter。

二、自定義Starter

首先先介紹幾個條件註解。

  • @ConditionalOnBean:當容器裏有指定的Bean爲true
  • @ConditionalOnClass:當類路徑下有指定的類爲true
  • @ConditionalOnMissingBean:當容器裏沒有指定的Bean爲true
  • @ConditionalOnProperty:指定的數據是否有指定的值
  • ...

瞭解了條件註解後,我們開始自定義Starter。

  • 1、在自定義Starter之前先要在Maven中填寫依賴。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <groupId>cn.miaolovezhen</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <name>spring-boot-starter-test</name>
   <description>Demo project for Spring Boot</description>
 
   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.6.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>
 
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>
 
   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-autoconfigure</artifactId>
         <version>1.5.4.RELEASE</version>
      </dependency>
   </dependencies>
 
</project>
  • 2、完成TestProperties類,這個類定義了默認的屬性值,如該類中,只有一個屬性值msg,默認爲world。@ConfigurationProperties註解會定義一個匹配,如果想修改屬性值,可以在application.properties中使用“匹配.屬性=修改的值”進行修改。如test.msg = tan
@ConfigurationProperties(prefix = "test")
public class TestProperties {
    private static final String MSG = "springboot";
    private String msg = MSG;
 
    public String getMsg() {
        return msg;
    }
 
    public void setMsg(String msg) {
        this.msg = msg;
    }
}
  • 3、完成服務類。服務類是指主要的功能類,如果沒有SpringBoot,這些服務類在Spring中都是需要自己去配置生成的。如SpringMVC中的DispatcherServlet、Mybatis的DataSource等。
public class TestService {
    private String msg;
 
    public String sayHello(){
        return "Hello " + msg;
    }
 
    public String getMsg() {
        return msg;
    }
 
    public void setMsg(String msg) {
        this.msg = msg;
    }
}
  • 4、完成自動配置類。自動配置類主要作用是SpringBoot的配置核心,它會寫在MEAT-INF/spring.factories中,告知SpringBoot在啓動時去讀取該類並根據該類的規則進行配置。
  • @EnableConfigurationProperties註解根據TestProperties類開啓屬性注入,允許在application.properties修改裏面的屬性值。
  • @ConditionOnClass會檢測是否存在TestService類
  • @ConditionOnProperty類會查看是否開啓該自動配置。默認開啓(true)。
  • @ConditionOnMissingBean會檢測容器中是否有TestService類的對象,如果沒有則生成一個。
@Configuration
@EnableConfigurationProperties(TestProperties.class)
@ConditionalOnClass(TestService.class)
@ConditionalOnProperty(prefix = "test" , value = "enabled" , matchIfMissing = true)
public class TestServiceAutoConfiguration {
    @Autowired
    TestProperties testProperties;
 
    @Bean
    @ConditionalOnMissingBean(TestService.class)
    public TestService testService(){
        TestService testService = new TestService();
        testService.setMsg(testProperties.getMsg());
        return testService;
    }
}
  • 5、最後一步,不要忘記在在MEAT-INF文件夾中創建spring.factories文件。內容很簡單,告訴SpringBoot去讀取TestServiceAutoConfiguration類。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.miaolovezhen.TestServiceAutoConfiguration

好啦,搞定!下面可以使用maven install命令把starter存到本地,其他SpringBoot項目需要使用這個starter,直接導入就可以啦。

 

參考:《java EE開發的顛覆者:springboot實戰》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章