Spring Conditional注解使用小结

今天我们来总结下Conditional注解的使用。

Conditional注解

增加配置类Config

package condition;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

/**
 * @author yaojiafeng
 * @create 2017-09-05 下午4:12
 */
@Configuration("config")
@Conditional(ConditionImpl.class)
public class Config {
    @Bean
    public String createString() {
        System.out.println("======000");
        return "String";
    }
}

增加Condition实现类ConditionImpl

package condition;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

/**
 * @author yaojiafeng
 * @create 2017-09-05 下午4:11
 */
public class ConditionImpl implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return true;
    }

}

编写测试类Main

package condition;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author yaojiafeng
 * @create 2017-09-05 下午4:18
 */
public class Main {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(Config.class);
        context.refresh();

        Object config = context.getBean("config");
        System.out.println(config);


    }
}

当调用context.register(Config.class)方法时,内部会调用方法。

public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}
                ......    

这里首先会执行conditionEvaluator.shouldSkip方法,这里面就是判断是否有Conditional注解,没有不需要跳过,有的话执行配置的条件类的matches方法,如果有一个类返回false,则跳过这个配置Bean(不加入到BeanDefinitionMap)。
把上面的matches方法返回值改为false,则会找不到这个配置Bean。
把Conditional注解配置在方法上也是一样的效果,因为在装载这个MethodBean的时候,也会调用ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod方法判断是否需要跳过这个MethodBean。

    @Bean("String")
    @Conditional(ConditionImpl.class)
    public String createString() {
        System.out.println("======000");
        return "String";
    }

下面是一些springboot的演变注解

ConditionalOnClass注解

在Config类上加ConditionalOnClass注解

@Configuration("config")
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class })
public class Config {

    @Bean("String")
    public String createString() {
        System.out.println("======000");
        return "String";
    }

}

registerBean的时候会递归查询是否包含Conditional注解,并取出他的配置Condition实现类,调用matches方法判断是否需要跳过。

ConditionalOnProperty注解

这个注解也是解析是否存在配置属性

@Configuration("config")
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class Config {

    @Bean("String")
    public String createString() {
        System.out.println("======000");
        return "String";
    }

}

其余类似的Conditional注解的解析过程大同小异,都有各自的Condition实现类,我们也可以自定义实现一套规则匹配。

原文地址:https://www.cnblogs.com/yaojf/p/7479082.html