SpringBoot的自动配置 (2)

这里主要的看调用这个方法getCandidateConfigurations,返回的就是要自动加载的Bean

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; }

通过META-INF/spring.factories配置文件里的EnableAutoConfiguration获取配置的Bean

# 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,\ .....

太多了,有兴趣的可以查看Spring的xxx-autoconfigure包。将读取到的配置最终返回给selectImports,然后通过工具类StringUtils.toStringArray转换为字符串数组返回给@Import,从而实现自动配置。第三方包只要是xxx-autoconfigure结尾的包,META-INF都有spring.factories,这个名字是固定写法。都可以被SpringBoot识别并且进行自动配置,前提是需要配置到org.springframework.boot.autoconfigure.EnableAutoConfiguration下。
从以上总结来看,SpringBoot的自动配置原理如下:

@EnableAutoConfiguration注解内部使用Import(AutoConfigurationImportSelector.class)来加载配置类

通过配置文件:META-INF/spring.factories,配置大量的配置类,SpringBoot启动时就会自动加载这些类并初始化的Bean。

这里需要说明一点,并不是所有配置到配置文件的Bean都会被初始化,需要符合配置类中使用Condition来加载满足条件的Bean。比如我们打开RedisAutoConfiguration的源码查看:

@Configuration( proxyBeanMethods = false ) @ConditionalOnClass({RedisOperations.class}) @EnableConfigurationProperties({RedisProperties.class}) @Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class}) public class RedisAutoConfiguration { public RedisAutoConfiguration() { } @Bean @ConditionalOnMissingBean( name = {"redisTemplate"} ) @ConditionalOnSingleCandidate(RedisConnectionFactory.class) public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<Object, Object> template = new RedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; } @Bean @ConditionalOnMissingBean @ConditionalOnSingleCandidate(RedisConnectionFactory.class) public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; } }

类上面有这么个注解@ConditionalOnClass({RedisOperations.class}),意思就是需要RedisOperations类存在的情况下,才自动加载;这还不算完,继续查看下面的方法上有个@ConditionalOnMissingBean(name = {"redisTemplate"}),这里的意思是,当其他地方没有redisTemplate实例化这个Bean时,才自动加载。符合这两个条件,SpringBoot才会进行自动加载并初始化。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyszpw.html