首页 > 其他分享 >SpringBoot-----SpringBoot @Conditional注解自动配置报告

SpringBoot-----SpringBoot @Conditional注解自动配置报告

时间:2022-08-14 19:36:42浏览次数:46  
标签:SpringBoot Conditional springframework Bean ----- context org import public

一、@Conditional简介

@Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册Bean。SpringBoot是根据配置文件的内容决定是否创建Bean,以及如何创建bean到Spring容器中,而Spring Boot自动化配置的核心控制,就是@Conditional注解。

二、@ConditionalOnXX注解

@ConditionalOnXX注解被定义在org.springframework.boot.autoconfigure包下面的condition文件夹下,它是一种条件装配,满足Conditional指定的条件,则进行组件注入

 

 在ideal中使用ctrl+H可以看到@Conditional的根注解和派生注解,这个根注解下派生了很多派生注解

 

@Conditional扩展注解 作用(判断是否满足当前指定条件)
@ConditionalOnJava 系统的java版本是否符合要求
@ConditionalOnBean 容器中存在指定Bean
@ConditionalOnMissingBean 容器中不存在指定Bean
@ConditionalOnExpression 满足SpEL表达式指定
@ConditionalOnClass 系统中有指定的类
@ConditionalOnMissingClass 系统中没有指定的类
@ConditionalOnSingleCandidate 容器中只有一个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty 系统中指定的属性是否有指定的值
@ConditionalOnResource 路径下是否存在指定资源文件
@ConditionalOnWebApplication 当前是web环境
@ConditionalOnNotWebApplication 当前不是web环境
@ConditionalOnJndi JNDI存在指定项

举例说明:

一、加载2个Bean

1、新建一个BeanConfig.java,利用@Configuration+@Bean加载2个Bean

package com.zk.autoconfigdemo;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BeanConfig {
    /*
     *如果windowsCondition的实现方法返回true,则注入这个bean
     */
    @Bean
    public Person person1(){
        return  new Person("BillGates",62);
    }
    /**
     * 如果LinuxCondition的实现方法返回true,则注入这个Bean
     */
    @Bean
    public Person person2(){
        return  new Person("Linus",50);
    }
} 

2、新建一个Person.java类

package com.zk.autoconfigdemo;

public class Person {
    private String name;
    private Integer age;

    public Person(String name, int age) {
        this.name=name;
        this.age=age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

3、测试是否都加载到Spring容器中

 AutoconfigdemoApplication.java

package com.zk.autoconfigdemo;

import org.apache.catalina.core.ApplicationContext;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.Map;

@SpringBootApplication
public class AutoconfigdemoApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext run=SpringApplication.run(AutoconfigdemoApplication.class,args);
        Map<String,Person> personMap=run.getBeansOfType(Person.class);
        System.out.println(personMap);
    }

}

 运行结果如下:

 

 二、利用@Conditional根据条件加载Bean

1、创建条件判断的类

如果是Windows系统则加载Bean

WindowsCondition.java

package com.zk.autoconfigdemo;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class WindowsCondition implements Condition {
    /**
     *
     * @param context:判断条件能使用的上下文环境
     * @param metadata:注解所在位置的注释信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //获取ioc使用的BeanFactory
        ConfigurableListableBeanFactory beanFactory=context.getBeanFactory();
        //获取类加载器
        ClassLoader classLoader=context.getClassLoader();
        //获取当前环境信息
        Environment environment=context.getEnvironment();
        //获取bean定义的注册类
        BeanDefinitionRegistry registry=context.getRegistry();

        //获取当前系统名
        String property=environment.getProperty("os.name");
        //包含windows说明是windows系统,返回true
        if(property.contains("Windows")){
            return true;
        }
        return false;
    }
}

 如果是Linux系统则加载Bean

LinuxCondition.java

package com.zk.autoconfigdemo;

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

public class LinuxCondition implements Condition{
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment=context.getEnvironment();

        String property = environment.getProperty("os.name");
        if(property.contains("Linux")){
            return true;
        }
        return false;
    }
}

 将@Conditional放在方法上

 BeanConfig.java

package com.zk.autoconfigdemo;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BeanConfig {
    /*
     *如果windowsCondition的实现方法返回true,则注入这个bean
     */
    @Bean
    @Conditional(WindowsCondition.class)
    public Person person1(){
        return  new Person("BillGates",62);
    }
    /**
     * 如果LinuxCondition的实现方法返回true,则注入这个Bean
     */
    @Bean
    @Conditional(LinuxCondition.class)
    public Person person2(){
        return  new Person("Linus",50);
    }
}

 或者将@Conditional注解放在类上

BeanConfig.java

package com.zk.autoconfigdemo;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
@Conditional(WindowsCondition.class)
public class BeanConfig {
    /*
     *如果windowsCondition的实现方法返回true,则注入这个bean
     */
    @Bean
    public Person person1(){
        return  new Person("BillGates",62);
    }
    /**
     * 如果LinuxCondition的实现方法返回true,则注入这个Bean
     */
    @Bean
    public Person person2(){
        return  new Person("Linus",50);
    }
}

 运行AutoconfigdemoApplication.java

package com.zk.autoconfigdemo;

import org.apache.catalina.core.ApplicationContext;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.Map;

@SpringBootApplication
public class AutoconfigdemoApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext run=SpringApplication.run(AutoconfigdemoApplication.class,args);
        Map<String,Person> personMap=run.getBeansOfType(Person.class);
        System.out.println(personMap);
    }

}

 得到的结果如下:

 

 因为当前系统为windows,所以只返回一个值。

 

 

标签:SpringBoot,Conditional,springframework,Bean,-----,context,org,import,public
From: https://www.cnblogs.com/longlyseul/p/16586102.html

相关文章

  • 洛谷P6812「MCOI-02」Ancestor 先辈
    洛谷P6812对于题目的区间加法明显可以用线段树或树状数组进行并且由题可得,先辈序列即为不下降序列,需满足ai<aj&&i<j判断一个序列是否为先辈我们比较的是一个元素和前一......
  • 洛谷 P6789 - 寒妖王(子集卷积+矩阵树定理)
    洛谷题面传送门像极了我验的那道牛客多校(第六场CForest)……考虑对于每条边,计算其在最大生成基环森林中的概率,乘以边权求和就是答案。现在问题在于如何计算每条边在最大......
  • CF EDU 96 E - String Reversal
    贪心、逆序对E-StringReversal题意给一个长度为n的字符串s,(n<=2e5),把s反转后的字符串记为s',每次只可以交换相邻两个字符,求把s变为s'的最小次数思路......
  • leetcode3-无重复字符的最长子串
    无重复字符的最长子串滑动窗口需要记录左边界left。当右边界移动的时候,如果新加入的字符已经存在,那么需要更新左边界,让left取左边界和上一个字符位置的最大值。之后更......
  • 【SpringBoot】学习笔记-MVC
     自动配置了ViewResolver,就是我们之前学习的SpringMVC的视图解析器;即根据方法的返回值取得视图对象(View),然后由视图对象决定如何渲染(转发,重定向)。我们去看看这里的源码......
  • 戏开发程序岗面试题答案版(一)-- C++篇
     游戏开发程序岗面试题答案版C++篇, 后续继续更新游戏逻辑篇、unity篇、图形学篇,并整理成文档,可在公号【游戏君五尘】获取。 网页排版排版较乱,原文链接游戏开......
  • leetcode1-两数之和
    两数之和暴力遍历classSolution{publicint[]twoSum(int[]nums,inttarget){intn=nums.length;for(inti=0;i<n;i++){......
  • CF EDU 97 E - Make It Increasing
    LISE-MakeItIncreasing题意给定数组$a$,(n<=5e5),有一个集合b,b里面存的是a数组的某些下标,这些位置的a的值不能改变其余位置可花1代价变为任意一个整......
  • leetcode2-两数相加
    两数相加循环,每次相加都new一个新的节点classSolution{publicListNodeaddTwoNumbers(ListNodel1,ListNodel2){ListNodehead=null,tail=nu......
  • tauri学习(1)-初体验
    tauri是一个类似Electron的框架,对于开发者最大的区别是后端语言用的是Rust,而且生成的可执行程序更小,今天尝试了下,感觉还不错,按官网的做法,只需执行下的命令(mac环境)npmc......