Spring Boot @Conditional 条件装配

来自姬鸿昌的知识库
跳到导航 跳到搜索

https://www.bilibili.com/video/BV19K4y1L7MT/?p=10

@Conditional 指定满足指定条件,才会将组件装配到容器中,IDEA 中选中 Conditional,按 F4 查看子类

@ConditionalOnBean

容器中存在指定类的组件的时候才会将当前注解的类的组件装配到容器中

@ConditionalOnMissingBean

容器中不存在指定类组件的时候才会将当前注解的类的组件装配到容器中

@ConditionalOnClass

当 classpath 中有指定类的时候才会将当前注解的类的组件装配到容器中

@ConditionalOnMissingClass

当 classpath 中有没有指定类的时候才会将当前注解的类的组件装配到容器中

@ConditionalOnResource

当 classpath 中存在指定资源的时候才会将当前注解的类的组件装配到容器中

@ConditionalOnJava

当运行环境的 Java 版本号满足指定条件的时候才会将当前注解的类的组件装配到容器中

@ConditionalOnWebApplication

当是一个 Web 应用的时候才会将当前注解的类的组件装配到容器中

@ConditionalOnNotWebApplication

当不是一个 Web 应用的时候才会将当前注解的类的组件装配到容器中

@ConditionalOnSingleCandidate

表示当指定Bean在容器中只有一个,或者虽然有多个但是指定首选Bean(primary)的时候

……


测试使用 @ConditionalOnBean 进行条件装配

修改 MyConfig,取消组件 tom 的装配

@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = false) //告诉 SpringBoot 这是一个配置类 == 配置文件
public class MyConfig {

    /**
     * 给容器中添加组件。
     * 以方法名作为组件的id。
     * 返回类型就是组件类型。
     * 返回的值,就是组件在容器中的实例
     *
     * 外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
     * @return
     */
    @Bean
    public User user01() {
        User zhangsan = new User("zhangsan", 18);
        zhangsan.setPet(tomcatPet());
        return zhangsan;
    }

//    @Bean("tom")
    public Pet tomcatPet() {
        return new Pet("tomcat");
    }

}
@SpringBootApplication(scanBasePackages = "io.github.jihch")
public class MainApplication {

    public static void main(String[] args) {
        //1、返回 IOC 容器
        ConfigurableApplicationContext context = SpringApplication.run(MainApplication.class, args);

        //2、查看容器里面的组件
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        Arrays.sort(beanDefinitionNames);
        for (String name : beanDefinitionNames) {
            System.out.println(name);
        }

        boolean tom = context.containsBean("tom");
        System.out.println("容器中 tom 组件:" + tom);

        boolean user01 = context.containsBean("user01");
        System.out.println("容器中 user01 组件:" + user01);
    }

}
……
容器中 tom 组件:false
容器中 user01 组件:true

使用 @ConditionalOnBean 实现没有 tom 就不进行 user01 的装配

……    
    @ConditionalOnBean(name = "tom")
    @Bean
    public User user01() {
        User zhangsan = new User("zhangsan", 18);
        zhangsan.setPet(tomcatPet());
        return zhangsan;
    }
……

重新运行 MainApplication

……
容器中 tom 组件false
容器中 user01 组件false

验证成功

测试装载 tomcatPet bean,但装载为不满足 @ConditionalOnBean name 条件的 bean

    @Bean("tom22")
    public Pet tomcatPet() {
        return new Pet("tomcat");
    }

再修改、运行 MainApplication

        ……
        boolean tom = context.containsBean("tom");
        System.out.println("容器中 tom 组件:" + tom);

        boolean user01 = context.containsBean("user01");
        System.out.println("容器中 user01 组件:" + user01);

        boolean tom22 = context.containsBean("tom22");
        System.out.println("容器中 tom22 组件:" + tom22);
        ……
容器中 tom 组件:false
容器中 user01 组件:false
容器中 tom22 组件:true



测试使用 @ConditionalOnMissingBean 进行条件装配

@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = false) //告诉 SpringBoot 这是一个配置类 == 配置文件
@ConditionalOnMissingBean(name = "tom")
public class MyConfig {

    /**
     * 给容器中添加组件。
     * 以方法名作为组件的id。
     * 返回类型就是组件类型。
     * 返回的值,就是组件在容器中的实例
     *
     * 外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
     * @return
     */
    @Bean
    public User user01() {
        User zhangsan = new User("zhangsan", 18);
        zhangsan.setPet(tomcatPet());
        return zhangsan;
    }

    @Bean("tom22")
    public Pet tomcatPet() {
        return new Pet("tomcat");
    }

}

再运行 MainApplication

……
容器中 tom 组件:false
容器中 user01 组件:true
容器中 tom22 组件:true