springboot自动配置是如何实现的?

什么是SpringBoot自动配置?
springboot的自动配置,指的是springboot会自动将一些配置类的bean注册进ioc容器,我们可以需要的地方使用@autowired或者@resource等注解来使用它。

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则会将标注的类注册到容器中。

SpringBoot中对@Conditional的引用链如下:
1、main方法所在类的@SpringBootApplication注解

在这里插入图片描述

2、点进去之后可以看到SpringBootApplication注解类上有一个@EnableAutoConfiguration

在这里插入图片描述

3、EnableAutoConfiguration注解类上有一个@Import(AutoConfigurationImportSelector.class)

在这里插入图片描述
这里就会扫描具有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容器。