@Conditional条件装配
  • @Conditional是Spring Framework提供的一个核心功能注解,这个注解的作用是提供自动装配的条件限制,一般我们在用@Configuration,@Bean的时候使用它。
  • 也就是我们在自定义Bean的注入的时候,我们可以通过@Condition来对bean的注入增加逻辑判断,符合我们要求的我们才让他自动装配
@Conditional 的使用
  • 如下注解源码是@Condition
@FunctionalInterface
public interface Condition {

	/**
	 * Determine if the condition matches.
	 * @param context the condition context
	 * @param metadata metadata of the {@link org.springframework.core.type.AnnotationMetadata class}
	 * or {@link org.springframework.core.type.MethodMetadata method} being checked
	 * @return {@code true} if the condition matches and the component can be registered,
	 * or {@code false} to veto the annotated component's registration
	 */
	boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);

}
  • condition是一个函数式接口,提供了一个matches方法,主要提供一个条件匹配的规则,返回表示是否可以注入Bean。
  • @Conditional 的注解来声明如下,他可以接受接收一个Condition的数组
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {

	/**
	 * All {@link Condition Conditions} that must {@linkplain Condition#matches match}
	 * in order for the component to be registered.
	 */
	Class<? extends Condition>[] value();

}
Conditional使用Demo
  • 我们通过对以上Conditional的了解来自己实现一个Bean的按自定义条件的装配:
  • 定义一个Condition,判断系统来返回是否装配:
/**
 * Created by jiamin5 on 2022/3/10.
 */
public class GpCondition implements Condition{
    private static final Logger logger = LoggerFactory.getLogger(GpCondition.class);

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String os = context.getEnvironment().getProperty("os.name");
        logger.info("GpCondition matthes osName:{}", os);
        if(os.contains("Windows")){
            return true;
        }
        return false;
    }
}
  • 定义配置类,装载一个BeanTestClass
/**
 * Created by jiamin5 on 2022/3/10.
 */
@Configuration
public class ConditionConfig {

    @Bean
    @Conditional(GpCondition.class)
    public BeanTestClass beanTestClass(){
        return new BeanTestClass();
    }
}
  • 如上,我们在BeanTestClass上增加了一个@Conditional(GpCondition.class),其中的具体条件就是我们自定义的注入限制条件类。
  • 意思就是,当条件满足我们定义的GpCondition的时候,我们就注入,否则不注入。
  • 依然在Application启动类中添加对新定义Bean的获取,如下
/**
 * @author liaojiamin
 * @Date:Created in 11:08 2022/3/7
 */
@SpringBootApplication
@EnableAutoImport
public class Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext ca = SpringApplication.run(Application.class, args);
        System.out.println(ca.getBean(FilterFirstObj.class));
        BeanTestClass beanTestClass = ca.getBean(BeanTestClass.class);
        System.out.println(beanTestClass);
    }
}
  • 当我们在Mac os上运行,有如下结果

springboot配置bean覆盖 springboot装配bean_加载

Spring Boot 中的@Conditional
  • 在SpringBoot中,有针对@Conditional的扩展,提供了更简单的使用方式,扩张了各种类型的注解,如下:
  • ConditionalOnBean/ConditionalOnMissBean 容器中存在或者不存在某个类的时候进行Bean加载
  • ConditionalOnClass/ConditionalOnMissClass:classpath下存在或者不存在指定类的时候进行Bean加载
  • ConditionalOnCloudPlatform:只允许在指定的云平台上才加载指定Bean
  • ConditionalOnExpression:基于SpEl表达式的条件判断
  • ConditionalOnJava:只允许在指定版本Java才加载Bean
  • ConditionalOnJndi:只有指定资源通过JNDI加载后才加载Bean
  • ConditionalOnWebApplication/ConsitionalOnNotWebApplication:如果是活着不是web应用才加载指定的Bean
  • ConditionalOnProperty:系统中指定对呀的属性是否有对应值
  • ConditionOnResource:要加载的Bean依赖指定资源是否存在于classpath
  • ConditionOnSingleCandidate:只有在确定了给定Bean的单个候选项时候才会加载Bean
  • 以上这些都在spring-boot-autoconfiguration.jar 中
  • springboot配置bean覆盖 springboot装配bean_spring boot_02

其他注入方式spring-autoconfigure-metadata
  • 除了@Conditional注解。Spring Boot中提供了spring-autoconfigure-metadata.properties文件来实现批量自动装配条件配置
  • 与@Conditional意义,只是将条件放在的文件,我们可以在spring-boot-autoconfigure.jar中找到这种配置
  • springboot配置bean覆盖 springboot装配bean_springboot配置bean覆盖_03

  • 同样遵循“约定由于配置”,通过这种配置实现条件过滤需保证两个前提条件:
  • 如上图中,文件路径名称必须是/META-INF/spring-autoconfigure-metadata.properties
  • 配置文件的key’的配置格式:自动配置类的类全路径名.条件 = 值
  • 这种配置优点在于可以有效降低Spring Boot启动时间,通过这种过滤方式减少配置陪的加载数量,因为这个过滤发生在配置类的装载之前,所以他可以降低Spring Boot启动时装载Bean的耗时

上一篇:SpringBoot自动装配源码解析