什么是自动装配?
Spring提供了向Bean中自动注入依赖的这个功能,这个过程就是自动装配。
SpringBoot的自动装配原理基于大量的条件注解ConditionalOnXXX,因此要先来了解一下条件注解相关的源码。
以ConditionalOnClass为例
首先来查看ConditionalOnClass的源码
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class)
public @interface ConditionalOnClass {
Class<?>[] value() default {};
String[] name() default {};
}
可以看到ConditaionalOnClass注解上面又存在一个@Conditaional(OnClassCondition.class)注解。对于这种关系,我们把@ConditionalOnClass注解叫做@Conditonal注解的派生注解。
自动装配原理建立在这些大量的派生注解@ConditionalOnXXX之上,而这些条件注解的原理又和Condition接口有关。
具体我们可以去看OnClassCondition.class类的继承实现关系,发现的确实现了Condition接口。可以多看其他类的继承实现关系图来证明。
这里我就不多粘贴了,那么我们去看Condition接口的源码
@FunctionalInterface
public interface Condition {
boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}
该接口只有一个方法,这个方法决定了是否要注册相应的bean对象,这个方法中存在两个参数,他们分别用来获取一些环境信息和注解元数据从而用在matches方法中判断是否符合条件。
最后我们自定义一个条件注解方便我们更好理解这些东西
创建条件判断类去实现Condition接口
class OnLinuxCondition implements Condition{
@Override
public final boolean matches(ConditionContext context,AnnotatedTypeMetadata metadata) {
//根据metadata获取对应注解上的信息
List<AnnotationAttributes> allAnnotationAttributes =
//返回值是一个类似Map的数据结构,但这里用List接收(实际上不能这么些)
metadata.getAllAnnotationAttributes(ConditionalOnLinux.class.getName());
//获得注解上的信息后遍历得到我想要得到的数据
for(AnnotationAttributes annotationAttributes:allAnnotationAttributes){
String environment = annotationAttributes.getString("environment");
if("linux".equals(environment)){
return true;
}
}
return false;
}
}
创建条件注解
@Target({
ElementType.TYPE,
ElementType.METHOD
})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnLinuxCondition.class)
class @interface ConditionalOnLinux(){
String environment() default "";
}
测试
@Configuration
class LinuxConfig{
@Bean
@ConditionalOnLinux(environment = "linux")
public Environment environment(){
return new LinuxEnvironment();
}
}
以上代码的意思是,如果想要注册environment的bean,那么它的环境属性一定是linux时,才会注册到容器当中。