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

本文详细解释了SpringBoot中的自动装配机制,特别关注了`ConditionalOnClass`等条件注解的作用,以及如何自定义条件判断。通过Condition接口的匹配逻辑,展示了如何根据特定环境(如Linux)动态决定Bean的注册。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是自动装配?

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zmbwcx2003

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值