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文件里。

 


原文地址:https://www.cnblogs.com/pjfmeng/p/14448611.html