Springboot @Condition注解 (配合其他注解使用,满足条件执行相应配置)

@Condition注解功能还是比较强大的,一般配合其他注解一起使用去配置Bean。从使用中可以深切体会到Spring设计的代码复用性高和耦合性低的特点,因为这个注解类似于模块化的条件判断语句。

  • 项目结构:
    在这里插入图片描述
  • 条件类的实现,其实现了Spring定义的Condition类
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class MacOSCondition implements Condition {

    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {

        //1
        conditionContext.getBeanFactory();
        //2
        conditionContext.getClassLoader();
        //3
        String property = conditionContext.getEnvironment().getProperty("os.name");
        //4
        conditionContext.getRegistry();
        //5
        conditionContext.getResourceLoader();

        //annotatedTypeMetadata.getAllAnnotationAttributes();

        if(property.contains("Mac")){
            return true;
        }
        return false;
    }
}

观察代码,我们可以发现:从重写方法的两个参数中可以获取应用上下文的许多变量参数,从而判断一些条件并加上一些逻辑代码;再返回boolean,告诉Spring是否执行相应的操作。

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

public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        String property = conditionContext.getEnvironment().getProperty("os.name");
        if(property.contains("Windows")){
            return true;
        }
        return false;
    }
}
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 property = conditionContext.getEnvironment().getProperty("os.name");
        if(property.contains("Linux")){
            return true;
        }
        return false;
    }
}
  • @Condition注解结合@Bean使用,注解在方法上。当满足条件,创建相应实例并注入容器。
import com.michael.annotation.demo.POJO.Person;
import com.michael.annotation.demo.condition.LinuxCondition;
import com.michael.annotation.demo.condition.MacOSCondition;
import com.michael.annotation.demo.condition.WindowsCondition;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.*;

@Configuration
@ComponentScan(value = {"com.michael"},
excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {SpringBootApplication.class})
})
public class MyConfig {
    @Lazy
    @Bean
    @Scope(value = "singleton")
    public Person person(){
        System.out.println("get");
        return new Person("Steven", 11);
    }

    @Conditional(value = {MacOSCondition.class})
    @Bean("Mac")
    public Person person1(){
        return new Person("Mac", 20);
    }

    @Conditional(value = {WindowsCondition.class})
    @Bean("Windows")
    public Person person2(){
        return new Person("Windows", 20);
    }

    @Conditional(value = {LinuxCondition.class})
    @Bean("Linux")
    public Person person3(){
        return new Person("Linux", 20);
    }
}
import com.michael.annotation.demo.POJO.Person;
import com.michael.annotation.demo.configuration.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import static java.lang.System.out;
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
        ApplicationContext applicationContext  =  new AnnotationConfigApplicationContext(MyConfig.class);
        for(String name : applicationContext.getBeanDefinitionNames()){
            out.println(name);
        }
    }
}
  • 测试输出:
get
2020-03-20 11:47:15.369  INFO 10583 --- [           main] c.m.annotation.demo.DemoApplication      : Started DemoApplication in 0.55 seconds (JVM running for 0.918)
get
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myConfig
personService
person
Mac

从输出可以发现,因为当前操作系统为Mac OS X,所以对应的Bean被创建并且注入了容器。

  • 当@Condition注解到类上,可以作用到类中的其他注解。

  • 除了@Condition这个原生注解,Spring提供了一些组合注解给我们使用

  1. @ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个Bean)
  2. @ConditionalOnClass(某个class位于类路径上,才会实例化一个Bean)
  3. @ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean)
  4. @ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean)
  5. @ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化一个Bean)
  6. @ConditionalOnNotWebApplication(不是web应用)

  7. 在这里插入图片描述
  • 代码演示使用@ConditionalOnBean:
import com.michael.annotation.demo.POJO.Person;
import com.michael.annotation.demo.condition.LinuxCondition;
import com.michael.annotation.demo.condition.MacOSCondition;
import com.michael.annotation.demo.condition.WindowsCondition;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.*;

@Configuration
@ComponentScan(value = {"com.michael"},
excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {SpringBootApplication.class})
})
public class MyConfig {
    @ConditionalOnBean(name = {"myConfig"})
    @Lazy
    @Bean
    @Scope(value = "singleton")
    public Person person(){
        System.out.println("get");
        return new Person("Steven", 11);
    }

    @Conditional(value = {MacOSCondition.class})
    @Bean("Mac")
    public Person person1(){
        return new Person("Mac", 20);
    }

    @Conditional(value = {WindowsCondition.class})
    @Bean("Windows")
    public Person person2(){
        return new Person("Windows", 20);
    }

    @Conditional(value = {LinuxCondition.class})
    @Bean("Linux")
    public Person person3(){
        return new Person("Linux", 20);
    }
}

这里对person方法注解了@ConditionalOnBean(name = {“myConfig”})。

输出:

get
2020-03-20 15:38:13.329  INFO 11136 --- [           main] c.m.annotation.demo.DemoApplication      : Started DemoApplication in 0.494 seconds (JVM running for 0.817)
get
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myConfig
personService
person
Mac

把条件改@ConditionalOnBean(name = {“Mac”})

输出:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myConfig
personService
Mac

对比两次输出,可以发现Bean注入容器的顺序是按照代码代码顺序的。

发布了70 篇原创文章 · 获赞 4 · 访问量 3040

猜你喜欢

转载自blog.csdn.net/qq_34515959/article/details/104997010