什么是SpringBoot自动配置?
​ SpringBoot的自动配置,指的是SpringBoot会自动将一些配置类的bean注册进ioc容器,我们可以需要的地方使用@autowired或者@resource等注解来使用它。
​ “自动”的表现形式就是我们只需要引我们想用功能的包,相关的配置我们完全不用管,springboot会自动注入这些配置bean,我们直接使用这些bean即可。

SpringBoot如何实现自动配置?
其实说白了SpringBoot的自动配置,实际是依赖@Conditional来实现的。@Conditional是一个条件注解,是Spring4提供的一个新特性,用于根据特定条件来控制Bean的创建行为。

看下@Conditional的实现:

    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Conditional {
    
    	/**
    	 * All {@link Condition Conditions} that must {@linkplain Condition#matches match}
    	 * in order for the component to be registered.
    	 */
    	Class<? extends Condition>[] value();
    
    }

Conditional 注解类里只有一个 value 属性,是一个Condition 类型的数组。

看下Condition :

    @FunctionalInterface
    public interface Condition {
    	/**
    	 * Determine if the condition matches.
    	 * @param context the condition context
    	 * @param metadata metadata of the {@link org.springframework.core.type.AnnotationMetadata class}
    	 * or {@link org.springframework.core.type.MethodMetadata method} being checked
    	 * @return {@code true} if the condition matches and the component can be registered,
    	 * or {@code false} to veto the annotated component's registration
    	 */
    	boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
    }

从注释中可以得知如果这个方法返回true则会将标注的类注册到容器中。

方法里面有两个参数,AnnotatedTypeMetadata注解元数据类,可以判断一个类是否为注解,或获取一个注解类的所有属性以及对应的值。
ConditionContext则是专门为Condition服务的一个接口,可以从中获取到Spring容器的一些对象信息。

当一个 Bean 被 Conditional 注解修饰时,Spring容器会对数组中所有 Condition 接口的 matches() 方法进行判断,当其中所有 Condition 接口的matches()方法都为 ture 时,才会创建 Bean 。

SpringBoot中对@Conditional的引用链如下:
1、main方法所在类的@SpringBootApplication注解
在这里插入图片描述
2、点进去之后可以看到SpringBootApplication注解类上有一个@EnableAutoConfiguration
在这里插入图片描述
3、EnableAutoConfiguration注解类上有一个@Import(AutoConfigurationImportSelector.class)
在这里插入图片描述
在AutoConfigurationImportSelector类中会执行getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes)方法,里面有一行:
List configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
这里就会扫描具有MEAT-INF/spring.factories文件的jar包,得到所有的配置类:
在这里插入图片描述
找个spring.factories文件的内容看下:
在这里插入图片描述
在这里插入图片描述

看下@Conditional是如何作用在这些配置类上的,打开第一个配置类RabbitHealthIndicatorAutoConfiguration:

    @Configuration
    @ConditionalOnClass(RabbitTemplate.class)
    @ConditionalOnBean(RabbitTemplate.class)
    @ConditionalOnEnabledHealthIndicator("rabbit")
    @AutoConfigureBefore(HealthIndicatorAutoConfiguration.class)
    @AutoConfigureAfter(RabbitAutoConfiguration.class)
    public class RabbitHealthIndicatorAutoConfiguration extends
    		CompositeHealthIndicatorConfiguration<RabbitHealthIndicator, RabbitTemplate> {
    
    	private final Map<String, RabbitTemplate> rabbitTemplates;
    
    	public RabbitHealthIndicatorAutoConfiguration(
    			Map<String, RabbitTemplate> rabbitTemplates) {
    		this.rabbitTemplates = rabbitTemplates;
    	}
    
    	@Bean
    	@ConditionalOnMissingBean(name = "rabbitHealthIndicator")
    	public HealthIndicator rabbitHealthIndicator() {
    		return createHealthIndicator(this.rabbitTemplates);
    	}
    }

解释上面几个注解:
1、@Configuration标注这个类是一个配置类。
2、 @ConditionalOnClass(RabbitTemplate.class):判断当前classpath下是否存在RabbitTemplate,若是则将当前的配置类装载入spring容器。
3、 @ConditionalOnBean(RabbitTemplate.class):判断当前spring的applicationContext中是否存在RabbitTemplate,若是则将当前的配置类装载入spring容器。
4、@ConditionalOnEnabledHealthIndicator(“rabbit”):判断当前配置文件(application.yml)配置有management.health.rabbit.enabled = true 或者management.health.defaults.enabled = true,若是则将当前的配置类装载入spring容器。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐