springboot源碼解析


1、自動配置原理

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
        @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

   
}

可以看到有注解@EnableAutoConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    Class<?>[] exclude() default {};
    String[] excludeName() default {};

}

可以看到

@Import(AutoConfigurationImportSelector.class)

@Import可以導入向spring中導入組件 ,可以看下鏈接的文檔

接着看下AutoConfigurationImportSelector.selectImports()方法,
selectImports方法調用是在前面的refresh方法的invokeBeanFactoryPostProcessors中,感興趣的可以看下spring 源碼解析一(bean定義)
@Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        //如果AutoConfiguration沒開,返回
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        //將spring-autoconfigure-metadata.properties的鍵值對配置載入到PropertiesAutoConfigurationMetadata對象中並返回
        AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
                .loadMetadata(this.beanClassLoader);
        //獲取@EnableAutoConfiguration 注解的屬性
        AnnotationAttributes attributes = getAttributes(annotationMetadata);
        //從META-INF/spring.factories文件中獲取EnableAutoConfiguration所對應的configurations
        List<String> configurations = getCandidateConfigurations(annotationMetadata,
                attributes);
        // 去重,List轉Set再轉List
        configurations = removeDuplicates(configurations);
         // 從注解的exclude/excludeName屬性中獲取排除項
        Set<String> exclusions = getExclusions(annotationMetadata, attributes);
         // 對於不屬於AutoConfiguration的exclude報錯
        checkExcludedClasses(configurations, exclusions);
        // 從configurations去除exclusions
        configurations.removeAll(exclusions);
        // 應用過濾器AutoConfigurationImportFilter, 
        // 此過濾器檢查候選配置類上的注解如@ConditionalOnClass,如果要求的類在classpath 中不存在,則這個候選配置類會被排除掉
        configurations = filter(configurations, autoConfigurationMetadata);
        // 現在已經找到所有需要被應用的候選配置類 
        // 廣播事件 AutoConfigurationImportEvent
        fireAutoConfigurationImportEvents(configurations, exclusions);
        return StringUtils.toStringArray(configurations);
    }
 
        

 這部分代碼比較簡單,就是讀取META-INF/spring.factories文件,然后過濾EnableAutoConfiguration注解上的exclude,然后再根據去重,再根據@ConditionalOnClass匹配過濾

 

在spring.factories中可以發現redis,mq,jdbc等等自動啟動器,但是卻沒有發現mybatis的

其實也是,mybatis的包都是手動maven導進來的,可以看下mybatis的自動啟動器是怎么實現的

 

 有兩個包,一個是mybatis-spring-boot-starter,一個是mybatis-spring-boot-autoconfigure,starter里什么都沒有,就是添加了mybatis-spring-boot-autoconfigure的pom文件

可以發現autoconfigure下面也有一個spring.factories文件,里面有個MybatisAutoConfiguration,mybatis自己實現了自啟動功能

所以我們如果自己需要實現自動啟動器,也可以模仿mybatis實現一個,將實現的AutoConfiguration放到spring.factories文件里。

 

 

 



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM