SpringBoot中的Contdition注解

Contdition

只有在pom文件中导入了相关的坐标,该bean才会纳入到Spring的IOC容器中,示例:
只有在pom文件中导入了redis坐标,才能拿到redisTemplate

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

获取redis

@SpringBootApplication
public class HelloWorld {
    public static void main(String[] args) {

        //Springboot的主启动类的run方法会返回一个对象
        ConfigurableApplicationContext run = SpringApplication.run(HelloWorld.class, args);
        //使用该对象的getBean属性获取对应的bean
        Object redisTemplate = run.getBean("redisTemplate");
        System.out.print(redisTemplate);

    }
}

@Conditional 注解的应用场景

1. 可以根据自定义条件来决定是否创建Bean

//1. 创建一个User类
package com.atguigu.bean;

public class User {
}

//2.声明一个配置类用来决定创建Bean
//声明是一个配置类
@Configuration
public class UserConfig {

    //1.获取User这个Bean
    @Bean
    @Conditional(ClassCondition.class)  //此处是重点:@Conditional(ClassCondition.class) 返回true的时候才创建Bean
    public User user(){
        return new User();
    }
}

//3.创建ClassCondition 这个类,用来实现Condition这个接口,重写该接口的matches方法,在该方法里面判断返回true还是false
public class ClassCondition implements Condition { //Condition:调节接口

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

        boolean flag = true;
        try {
            Class<?> tClass = Class.forName("redis.clients.jedis.Jedis");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            flag = false;
        }
        
        return flag;
    }
}

 2. Bean可以动态指定

//通过导入坐标属性值Value后来创建Bean,即动态创建Bean原理
//1.首先自己写一个注解Annotation

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ClassCondition.class)  //把@Conditional(ClassCondition.class)这个注解放到自定义的注解上面
public @interface ConditionOnClass {

    //由于动态配置的bean可能会有多个,所以引入Sring数组,即ClassCondition配置类中可能写入了多个bean
    String [] value();
}

//2.声明是一个配置类
@Configuration
public class UserConfig {

    //1.获取User这个Bean
    @Bean
    @ConditionOnClass("redis.clients.jedis.Jedis")
    @ConditionalOnProperty(name = "swl",havingValue = "maky")
    //ConditionOnClass 这个注解就是上面咱们自定义的注解; 
    //条件是必须同时满足:  1. 如果引入了Jedis,  2. 配置文件中配置了键和值为swl=maky 则创建User
    public User user(){
        return new User();  //创建User的前提是必须加载一个坐标进来,就是redis
    }
}

//3.动态创建原理。 创建一个类用来实现Condition接口,重写该接口的Matches方法
public class ClassCondition implements Condition {

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

        //matches方法中共有两个参数:
        //conditionContext:上下文对象,可以获取环境对象、IOC容器、classloader对象。例如:可以加载配置文件中是否配置了那个属性
        //annotatedTypeMetadata:注解的元对象,可以获取注解对应的属性值
        
        //1.获取注解属性值value:annotatedTypeMetadata.getAnnotationAttributes();
        //2.值是多少:ConditionOnClass.class.getName(); 就是第一个自定义注解ConditionOnClass 里面String数组的value
        //3.值具体是:就是第二个自定义配置类中 @ConditionOnClass("redis.clients.jedis.Jedis") 的值  :redis.clients.jedis.Jedis 
        
        Map<String, Object> map = annotatedTypeMetadata.getAnnotationAttributes(ConditionOnClass.class.getName());
        String [] value = (String[]) map.get("value");
        
        boolean flag = true;
        try {
            //遍历value这个数组
            for (String classname : value) {
                Class<?> tClass = Class.forName(classname);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            flag = false;
        }
        return flag;
    }
}

小结

①定义条件类:

自定义类实现Condition接口,重写matches方法,在matches方法中进行逻辑判断,返回boolean值。matches方法两个参数:

  • context:上下文对象,可以获取属性值,获取类加载器,获取 BeanFactory 等。
  • metadata:元数据对象,用于获取注解属性。

②判断条件:

在初始化Bean时,使用@ conditional (条件类:class)注解
 SpringBoot 提供的常用条件注解:

  • ConditionalOnProperty :判断配置文件中是否有对应属性和值才初始化Bean
  • Conditional  Onclass:判断环境中是否有对应字节码文件才初始化Bean
  • ConditionalOnMissingBean :判断环境中没有对应Bean才初始化Bean

转载资源:B站黑马老师:陈一宏老师 Springboot- 6小时入门

 

posted @ 2022-03-24 23:46  许君闲乘悦  阅读(105)  评论(0编辑  收藏  举报