springboot自动配置是如何实现的?
什么是SpringBoot自动配置?springboot的自动配置,指的是springboot会自动将一些配置类的bean注册进ioc容器,我们可以需要的地方使用@autowired或者@resource等注解来使用它。“自动”的表现形式就是我们只需要引我们想用功能的包,相关的配置我们完全不用管,springboot会自动注入这些配置bean,我们直接使用这些bean即可。Sprin...
什么是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容器。
更多推荐
所有评论(0)