服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - spring @Conditional的使用与扩展源码分析

spring @Conditional的使用与扩展源码分析

2022-10-23 17:21morris131 Java教程

这篇文章主要介绍了spring @Conditional的使用与扩展,这里需要注意如果Condition返回的是false,那么spirng就不会对方法或类进行解析,具体源码分析跟随小编一起看看吧

@Conditional的使用

@Conditional可以根据条件来判断是否注入某些Bean。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.morris.spring.config;
 
import com.morris.spring.condition.LinuxCondition;
import com.morris.spring.condition.WindowsCondition;
import com.morris.spring.entity.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ConditionalConfig {
    // 如果是windows系统就注入bill
    @Conditional(WindowsCondition.class)
    @Bean(name = "user")
    public User bill() {
        return new User("bill", 22);
    }
    // 如果是linux系统就注入linus
    @Conditional(LinuxCondition.class)
    public User linus() {
        return new User("linus", 20);
}

WindowsCondition和LinuxCondition都需要实现Condition接口。

WindowsCondition

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.morris.spring.condition;
 
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class WindowsCondition implements Condition {
    /**
     * 根据条件判断是否注入对应的Bean
     * @param conditionContext 应用上下文
     * @param annotatedTypeMetadata 加了@Conditional注解的方法的元数据信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        String osName = conditionContext.getEnvironment().getProperty("os.name");
        if(osName.contains("Windows")) {
            return true;
        }
        return false;
    }
}

LinuxCondition

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.morris.spring.condition;
 
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class LinuxCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        String osName = conditionContext.getEnvironment().getProperty("os.name");
        if(osName.contains("linux")) {
            return true;
        }
        return false;
    }
}

如果要测试LinuxCondition并不需要再linux系统下运行,只需要的启动时设置环境参数:-Dos.name=linux

Conditional的扩展

ConditionalOnBean

ConditionalOnBeanc.java

?
1
2
3
4
5
6
7
8
9
10
11
package com.morris.spring.condition;
 
import org.springframework.context.annotation.Conditional;
import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnBean {
    Class<?>[] value() default {};
}

OnBeanCondition.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.morris.spring.condition;
 
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import java.util.Map;
public class OnBeanCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(ConditionalOnBean.class.getName());
        Class<?>[] clazz = (Class<?>[]) annotationAttributes.get("value");
        for (Class<?> aClass : clazz) {
            Map<String, ?> beans = context.getBeanFactory().getBeansOfType(aClass);
            if(beans.isEmpty()) {
                return false;
            }
        }
        return true;
    }
}

ConditionalOnProperty

ConditionalOnProperty.java

?
1
2
3
4
5
6
7
8
9
10
11
package com.morris.spring.condition;
 
import org.springframework.context.annotation.Conditional;
import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {
    String[] value() default {};
}

OnPropertyCondition.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.morris.spring.condition;
 
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import java.util.Map;
public class OnPropertyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(ConditionalOnProperty.class.getName());
        String[] propertyArray = (String[]) annotationAttributes.get("value");
        for (String property : propertyArray) {
            if(!context.getEnvironment().containsProperty(property)) {
                return false;
            }
        }
        return true;
    }
}

源码分析

如果Condition返回的是false,那么spirng就不会对方法或类进行解析。

org.springframework.context.annotation.ConditionEvaluator#shouldSkip

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
    // 判断类或方法上面是否有@Conditional注解
    if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
        return false;
    }
    if (phase == null) {
        if (metadata instanceof AnnotationMetadata &&
                ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
            return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
        }
        return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
    List<Condition> conditions = new ArrayList<>();
    for (String[] conditionClasses : getConditionClasses(metadata)) {
        for (String conditionClass : conditionClasses) {
            Condition condition = getCondition(conditionClass, this.context.getClassLoader());
            conditions.add(condition);
    AnnotationAwareOrderComparator.sort(conditions);
    for (Condition condition : conditions) {
        ConfigurationPhase requiredPhase = null;
        if (condition instanceof ConfigurationCondition) {
            requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
        // 调用condition.matches方法
        if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
            return true;
    return false;
}

到此这篇关于spring @Conditional的使用与扩展的文章就介绍到这了,更多相关spring @Conditional使用内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/u022812849/article/details/123729369

延伸 · 阅读

精彩推荐