解析SpringBoot自动装配原理前置知识:解析条件注释的原理

什么是自动装配?

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时,才会注册到容器当中。

相关推荐

  1. Spring自动装配解析原理与实践

    2024-03-24 13:56:02       30 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-24 13:56:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-24 13:56:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-24 13:56:02       82 阅读
  4. Python语言-面向对象

    2024-03-24 13:56:02       91 阅读

热门阅读

  1. 蓝桥杯 积木画 (dp)

    2024-03-24 13:56:02       38 阅读
  2. C#面:什么是 NuGet

    2024-03-24 13:56:02       39 阅读
  3. 富格林:利用可信技巧租阻止暗箱陷阱

    2024-03-24 13:56:02       43 阅读
  4. Kafka系列之:Connect 中的错误报告

    2024-03-24 13:56:02       43 阅读
  5. 【MySQL】覆盖索引

    2024-03-24 13:56:02       42 阅读
  6. 【LeetCode-394.字符串解码】

    2024-03-24 13:56:02       42 阅读
  7. 24.3.24 《CLR via C#》 笔记10

    2024-03-24 13:56:02       38 阅读
  8. 优化 - 数据结构

    2024-03-24 13:56:02       39 阅读
  9. 100268. 最长公共后缀查询(字典树查询)

    2024-03-24 13:56:02       39 阅读