親手實現一個springboot默認配置&起步加載

實現

一、創建springboot項目引入spring-boot-dependencies依賴
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-autoconfigure</artifactId>
		</dependency>

spring-boot-autoconfigure 是springboot自動配置依賴,springboot提供的默認配置都在這個依賴中

開啓自動配置註解:

  • @EnableAutoConfiguration
    • exclude = Class<?>[]
  • @SpringBootApplication (內部包含了@EnableAutoConfiguration)
二、創建配置類
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
//包含GreetingApplicationRunner這個類時纔會生效
@ConditionalOnClass(GreetingApplicationRunner.class)
public class GreetingAutoConfiguration {
    @Bean
    //當spring容器中沒有GreetingApplicationRunner類時加載
    @ConditionalOnMissingBean(GreetingApplicationRunner.class)
    // greeting.enabled 值等於 true時配置加載;matchIfMissing = true greeting.enabled值爲空時也加載
    @ConditionalOnProperty(name = "greeting.enabled", havingValue = "true", matchIfMissing = true)
    public GreetingApplicationRunner greetingApplicationRunner() {
        return new GreetingApplicationRunner();
    }
}
三、在resources目錄下創建META-INF/spring.factories 寫入:
# 自動配置
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
geektime.spring.hello.greeting.GreetingAutoConfiguration

@EnableAutoConfifiguration

  • AutoConfigurationImportSelector

  • META-INF/spring.factories

    • org.springframework.boot.autoconfigure.EnableAutoConfiguration

spring.factories 文件

注意:@Configuration註解和/spring.factories文件可以只寫一個,建議兩個都寫

四、實現起步依賴(啓動加載)

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;

@Slf4j
public class GreetingApplicationRunner implements ApplicationRunner {
    public GreetingApplicationRunner() {

        log.info("Initializing GreetingApplicationRunner.");
    }

    public void run(ApplicationArguments args) throws Exception {
        log.info("Hello everyone! We all like Spring! ");
    }
}

實現ApplicationRunner 接口可以實現起步加載

我們來看一下spring-boot-autoconfigure 中的META-INF/spring.factories文件寫了哪些內容

# Initializers 初始化 
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

# Application Listeners 監聽器
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer

#以上是於spring-cloud-context相關的jar




# 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.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition

# 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
#...
#springboot自動配置都在這裏配置,把你的配置類權限限定名寫在這裏

#以上是於spring-boot-autoconfigure相關的jar



# Failure analyzers  故障分析
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer


# Template availability providers 模板
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider

@Conditional 用法

使用@Conditional控制@Configuration 是否生效

作用:總而言之,只有@Conditional指定的條件成立,纔給容器添加組件

@Conditional派生註解:@Conditional派生了很多註解,下面給個表格列舉一下派生註解的用法

@Conditional派生註解 作用(都是判斷是否符合指定的條件)
@ConditionalOnJava 系統的java版本是否符合要求
@ConditionalOnBean spring容器有指定的Bean類
@ConditionalOnMissingBean spring容器沒有指定的bean類
@ConditionalOnExpression 符合指定的SpEL表達式
@ConditionalOnClass 有指定的類(好像是你的工程中存在這個類)
@ConditionalOnMissingClass 沒有指定的類(好像是你的工程中不存在這個類)
@ConditionalOnSingleCandidate 容器只有一個指定的bean,或者這個bean是首選bean
@ConditionalOnProperty 指定的property屬性有指定的值
@ConditionalOnResource 路徑下存在指定的資源
@ConditionalOnWebApplication 系統環境是web環境
@ConditionalOnNotWebApplication 系統環境不是web環境
@ConditionalOnjndi JNDI存在指定的項
@ConditionalOnClass

某個class位於類路徑上,纔會實例化一個Bean。即判斷當前classpath下是否存在指定類,若是則將當前的配置裝載入spring容器

ConditionalOnProperty

application.properties 屬性值符合指定條件時生效

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {
	//獲取對應property名稱的值,與name不可同時使用
    String[] value() default {};   
  	//property名稱的前綴,可有可無
    String prefix() default "";  
  	//property完整名稱或部分名稱(可與prefix組合使用,組成完整的property名稱),與value不可同時使用 
    String[] name() default {}; 
  	//可與name組合使用,比較獲取到的屬性值與havingValue給定的值是否相同,相同才加載配置  
    String havingValue() default "";
  	//缺少該property時是否可以加載。如果爲true,沒有該property也會正常加載;反之報錯  
    boolean matchIfMissing() default false;
  	//是否可以鬆散匹配,指命名方式支持駝峯橫線方式兼容 
    boolean relaxedNames() default true; 
} 
}

其中name用來從application.properties中讀取某個屬性值。如果該值爲空,則返回false(havingValue = "true"時返回true,默認havingValue = “false”);
如果值不爲空,則將該值與havingValue指定的值進行比較,如果一樣則返回true;否則返回false。
如果返回值爲false,則該configuration不生效;爲true則生效。

代碼:https://github.com/liuyanqing1023/geektime-spring-family/tree/master/Chapter%209

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