SpringBoot自动配置

1、SpringBoot的主配置类

@SpringBootApplication
public class SpringBootApplication {

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

}

可以看到,@SpringBootApplication包含了三个注解@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan

  1. @SpringBootConfiguration表示Spring的配置类

  2. @ComponentScan扫描符合规则的类并将其注入到Spring容器。其扫描路径可配置,默认是扫描被此注解修饰的类的包及其子包,所以SpringBoot的启动类一般都放在最高级包路径下。

  3. @EnableAutoConfiguration自动配置关键注解

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {@Filter(type = FilterType.CUSTOM, classes = {org.springframework.boot.context.TypeExcludeFilter.class}), @Filter(type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class})})
public @interface SpringBootApplication {

 }

2、@EnableAutoConfiguration

  1. @EnableAutoConfiguration包含@Import({AutoConfigurationImportSelector.class}),这个就是自动配置的重中之重。此类配合Import有批量注册bean的功能。
    @AutoConfigurationPackage
    @Import({AutoConfigurationImportSelector.class})
    public @interface EnableAutoConfiguration {
    
    }

    //ImportSelector实现类,此类配合Import有批量注册bean的功能
    public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,                                   ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
    	public String[] selectImports( AnnotationMetadata annotationMetadata ) {
    		if ( !isEnabled( annotationMetadata ) )
    		{
    			return(NO_IMPORTS);
    		}
            /*步骤一:读取 /META-INF/spring-autoconfigure-metadata.properties文件,
	          先筛选一下要加载哪些配置类,再把符合条件配置类的信息封装到AutoConfigurationMetadata*/
    		AutoConfigurationMetadata	autoConfigurationMetadata	= AutoConfigurationMetadataLoader.loadMetadata( this.beanClassLoader );
    		
    		/*步骤二:读取 META-INF/spring.factories文件,把其信息封装到
        	  AutoConfigurationEntry里,再将步骤一获取的配置类与此处获取的配置类
              执行过滤、去重、排序等操作,保存满足条件的配置类*/
    		AutoConfigurationEntry		autoConfigurationEntry		= getAutoConfigurationEntry( autoConfigurationMetadata, annotationMetadata );
    
            /*返回满足自动配置条件的类的字符串数组,后交给@Import注解,将其注入到Spring容器中,
              至此,完成SpringBoot的自动配置!*/
    		return(StringUtils.toStringArray( autoConfigurationEntry.getConfigurations() ) );
    	}
    }
    
    
  1. 点击进入getAutoConfigurationEntry方法,再进入getCandidateConfigurations方法就可以发现读取了包路径下META-INF/spring.factories里面配置的*AutoConfiguration自动配置类
    protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
            if (!this.isEnabled(annotationMetadata)) {
                return EMPTY_ENTRY;
            } else {
                AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
                
                //这里getCandidateConfigurations就是返回自动配置spring.factories配置项信息。
                List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
                //set去重
                configurations = this.removeDuplicates(configurations);
                Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
                this.checkExcludedClasses(configurations, exclusions);
                configurations.removeAll(exclusions);
                configurations = this.filter(configurations, autoConfigurationMetadata);
                this.fireAutoConfigurationImportEvents(configurations, exclusions);
                return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
            }
        }

     //getCandidateConfigurations读取spring.factories文件
     protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
            List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
            Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
            return configurations;
        }

spring-boot-autoconfigure包下META-INF/spring.factories,截取一部分。然后springboot就会帮我们把这些自动配置类条件性注册到ioc容器中。

# 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.CloudServiceConnectorsAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
  1. 通过@import注解读取并注册META-INF/spring.factories里的配置类*AutoConfiguration。
    以RedisAutoConfiguration配置类为例:
  • @Configuration说明这是一个config配置类;
  • @ConditionalOnClass表示某个class位于类路径上,才会实例化一个Bean;
  • @EnableConfigurationProperties使@ConfigurationProperties生效并被Configuration类的对应属性注入,这样就实现了我们自定义application.yml配置参数设置。
  • @ConditionalOnMissingBean 仅在当前上下文中不存在某个对象时,才会实例化一个Bean
    @Configuration
    @ConditionalOnClass({org.springframework.data.redis.core.RedisOperations.class})
    @EnableConfigurationProperties({RedisProperties.class})
    @Import({LettuceConnectionConfiguration.class,JedisConnectionConfiguration.class})
    public class RedisAutoConfiguration {
        @Bean
        @ConditionalOnMissingBean(name =  {"redisTemplate"})
        public RedisTemplate<Object, Object> redisTemplate(
            RedisConnectionFactory redisConnectionFactory)
            throws UnknownHostException {
            RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
            template.setConnectionFactory(redisConnectionFactory);
    
            return template;
        }
    
        @Bean
        @ConditionalOnMissingBean
        public StringRedisTemplate stringRedisTemplate(
            RedisConnectionFactory redisConnectionFactory)
            throws UnknownHostException {
            StringRedisTemplate template = new StringRedisTemplate();
            template.setConnectionFactory(redisConnectionFactory);
    
            return template;
        }
    }
    
    //RedisProperties数据源类,对应application.yml配置
    @ConfigurationProperties(prefix = "spring.redis")
    public class RedisProperties {
        private int database = 0;
        private String url;
        private String host = "localhost";
        private String password;
        private int port = 379;
        private boolean ssl;
        private Duration timeout;
        private Sentinel sentinel;
        private Cluster cluster;
    }

    

总结

  1. @SpringBootApplication等同于三个注解:@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan

  2. springboot启动时@EnableAutoConfiguration会扫描所有jar路径下META-INF/spring.factories,然后筛选出以EnableAutoConfiguration为key的数据,加载到IOC容器中,实现自动配置功能

  3. 每一个配置类装载的过程依赖于Properties的自定义属性,通过@Condition派生注解实现是否注入对应bean实现自动配置

参考

https://blog.csdn.net/qq_42459181/article/details/90899512

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值