最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring如何根據(jù)條件創(chuàng)建bean,@Conditional注解使用方式

 更新時間:2023年06月06日 15:13:02   作者:NameExist  
這篇文章主要介紹了Spring如何根據(jù)條件創(chuàng)建bean,@Conditional注解使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

Spring根據(jù)條件創(chuàng)建bean,@Conditional注解使用

spring提供了一個基于條件創(chuàng)建bean的注解@Conditional。

@Conditional注解定義

//1.可作用于類(接口)、方法上
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
? ? //2.需要傳入Condition類型的參數(shù)(繼承Condition接口)
? ? Class<? extends Condition>[] value();
}

@Conditional注解使用

1、定義一個類實(shí)現(xiàn)Condition接口,返回true則會創(chuàng)建bean,false則不會創(chuàng)建

public class MyCondition implements Condition {
? ? @Override
? ? public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
? ? ? ? return true;
? ? }
}

2,定義java配置類

@Configuration
public class BeanConfig {
? ? @Bean
? ? @Conditional({MyCondition.class})
? ? public User user(){
? ? ? ? User user = new User();
? ? ? ? user.setName("小明");
? ? ? ? return user;
? ? }
}

3、獲取bean

@Test
public void test(){
? ? AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
? ? //獲取bean,如果MyCondition返回flase則會報NoSuchBeanDefinitionException,注解注入@Autowired(required = false)
? ? User u = (User) context.getBean("user");
? ? System.out.println(u.toString());
}

@Conditional注解常用子注解 

springboot封裝conditional注解,在包org.springframework.boot.autoconfigure.condition下。

1、ConditionalOnProperty :當(dāng)配置文件熟悉值與注解配置的值一致時才會創(chuàng)建bean。prefix配置文件的前綴,name字段名,havingValue字段值

//當(dāng)配置文件 user.enable=1時才會創(chuàng)建bean,否則不會創(chuàng)建
@ConditionalOnProperty(prefix = "user", name = "enable",havingValue = "1")
@Bean
public User user(){
? ? User user = new User();
? ? user.setName("name");
? ? return user;
}

2、ConditionalOnBean 和 ConditionalOnMissingBean:當(dāng)某一個bean存在或不存在時才會創(chuàng)建bean。

@Bean
public Dept dept(){
? ? return new Dept();
}
/**
?* ConditionalOnBean 和 ConditionalOnMissingBean 跟bean的創(chuàng)建順序有關(guān),
?* 如果先創(chuàng)建了則ConditionalOnBean修飾的bean被創(chuàng)建,后創(chuàng)建傳入的bean類型則ConditionalOnMissingBean修飾的bean被創(chuàng)建
?* @return
?*/
@ConditionalOnBean(Dept.class)
@Bean
public User user(){
? ? User user = new User();
? ? user.setName("name");
? ? return user;
}
@ConditionalOnMissingBean(Dept.class)
@Bean
public User user1(){
? ? User user = new User();
? ? user.setName("name-1");
? ? return user;
}

3、ConditionalOnExpression:多個條件判斷,滿足則創(chuàng)建bean,可以用and 和 or。

/**
?* 多個條件判斷
?* @return
?*/
//@ConditionalOnExpression("'${user.enable}' == '1' and '${user.open}' == '2'")
@ConditionalOnExpression("'${user.enable}' == '1' or '${user.open}' == '2'")
@Bean
public User user(){
? ? User user = new User();
? ? user.setName("name");
? ? return user;
}

按照條件向Spring容器中注冊bean

1.@Conditional注解概述

@Conditional注解可以按照一定的條件進(jìn)行判斷,滿足條件向容器中注冊bean,不滿足條件就不向容器中注冊bean。

package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
	/**
	 * All {@link Condition} classes that must {@linkplain Condition#matches match}
	 * in order for the component to be registered.
	 */
	Class<? extends Condition>[] value();
}
  • @Conditional注解不僅可以添加到類上,也可以添加到方法上。
  • @Conditional注解中,還存在著一個Condition類型或者其子類型的Class對象數(shù)組。
package org.springframework.context.annotation;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.core.type.AnnotatedTypeMetadata;
@FunctionalInterface
public interface Condition {
	boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}

是一個接口,所以在使用@Conditional注解時,需要寫一個類來實(shí)現(xiàn)Spring提供的Condition接口,它會匹配@Conditional所符合的方法,然后就可以使用在@Conditional注解中定義的類來檢查了。

2.向Spring容器注冊bean

2.1.不帶條件注冊bean

package com.tianxia.springannotation.config;
import com.tianxia.springannotation.entity.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
/**
 * 配置類
 * @author liqb
 * @date 2023-04-23 9:45
 **/
@Configuration
public class MainConfig02 {
    /**
     * 創(chuàng)建person實(shí)例
     * @author liqb
     * @date 2023-04-23 09:46
     * @return
     */
    @Bean("person02")
    //通過@Scope注解來指定該bean的作用范圍,也可以說成是調(diào)整作用域
    @Scope("prototype")
    public Person person() {
        System.out.println("給容器中添加咱們這個Person對象...");
        return new Person("liqb", 24);
    }
    /**
     * 創(chuàng)建person實(shí)例 名為bill
     * @author liqb
     * @date 2023-04-23 12:47
     * @return
     */
    @Bean("bill")
    public Person person01() {
        return new Person("Bill Gates", 62);
    }
    /**
     * 創(chuàng)建person實(shí)例 名為linus
     * @author liqb
     * @date 2023-04-23 12:47
     * @return
     */
    @Bean("linus")
    public Person person02() {
        return new Person("linus", 48);
    }
}

測試兩個bean是否被注冊到Spring容器中

/**
 * 測試bill,linus是否被注入到spring中
 * @author liqb
 * @date 2023-04-23 12:50
 */
@Test
public void test06() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig02.class);
    // 查看IOC容器中Person這種類型的bean都有哪些
    String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
    for (String name : namesForType) {
        System.out.println(name);
    }
}

輸出的結(jié)果信息如下所示:

結(jié)論:說明默認(rèn)情況下,Spring容器會將單實(shí)例并且非懶加載的bean注冊到IOC容器中。

2.2.帶條件注冊bean

需求:比如,如果當(dāng)前操作系統(tǒng)是Windows操作系統(tǒng),那么就向Spring容器中注冊名稱為bill的Person對象;如果當(dāng)前操作系統(tǒng)是Linux操作系

統(tǒng),那么就向Spring容器中注冊名稱為linus的Person對象。要想實(shí)現(xiàn)這個需求,我們就得要使用@Conditional注解了。

  • LinuxCondition
package com.tianxia.springannotation.config.configCondition;
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;
/**
 * 判斷操作系統(tǒng)是否是Linux系統(tǒng)
 * @author liqb
 * @date 2023-04-23 12:56
 **/
public class LinuxCondition implements Condition{
    /**
     * 匹配方法
     * @author liqb
     * @date 2023-04-23 12:57
     * @param context 判斷條件能使用的上下文(環(huán)境)
     * @param metadata 當(dāng)前標(biāo)注了@Conditional注解的注釋信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // 判斷操作系統(tǒng)是否是Linux系統(tǒng)
        // 1. 獲取到bean的創(chuàng)建工廠(能獲取到IOC容器使用到的BeanFactory,它就是創(chuàng)建對象以及進(jìn)行裝配的工廠)
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        // 2. 獲取到類加載器
        ClassLoader classLoader = context.getClassLoader();
        // 3. 獲取當(dāng)前環(huán)境信息,它里面就封裝了我們這個當(dāng)前運(yùn)行時的一些信息,包括環(huán)境變量,以及包括虛擬機(jī)的一些變量
        Environment environment = context.getEnvironment();
        // 4. 獲取到bean定義的注冊類
        BeanDefinitionRegistry registry = context.getRegistry();
        // 在這兒還可以做更多的判斷,比如說我判斷一下Spring容器中是不是包含有某一個bean,就像下面這樣,如果Spring容器中果真包含有名稱為person的bean,那么就做些什么事情...
        boolean definition = registry.containsBeanDefinition("person");
        String property = environment.getProperty("os.name");
        if (property.contains("linux")) {
            return true;
        }
        return false;
    }
}

理解:通過context的getRegistry()方法獲取到的bean定義的注冊對象,即BeanDefinitionRegistry對象。

如下所示,可以看到它是一個接口

package org.springframework.beans.factory.support;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.core.AliasRegistry;
// spring容器中所有的bean都是通過BeanDefinitionRegistry對象來進(jìn)行注冊的
// 因此我們可以通過它來查看Spring容器中注冊了哪些bean
public interface BeanDefinitionRegistry extends AliasRegistry {
	// 該方法表明我們可以通過BeanDefinitionRegistry對象向5pring容器中注冊一個bean
	void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
	throws BeanDefinitionStoreException;
	// 該方法表明我們可以通過BeanDefinitionRegistry對象在Spring容器中移除一個bean
	void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
	// 該方法表明我們可以通過BeanDefinitionRegistry對象查看某個bean的定義信息
	BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
	// 該方法表明我們可以通過BeanDefinitionRegistry對象查看對象Spring
	// 容器中是否包含某一個bean的定義
	boolean containsBeanDefinition(String beanName);
	String[] getBeanDefinitionNames();
	int getBeanDefinitionCount();
	boolean isBeanNameInUse(String beanName);
}

可以通過BeanDefinitionRegistry對象向Spring容器中注冊一個bean、移除一個bean、查詢某一個bean的定義信息或者判斷Spring容器

中是否包含有某一個bean的定義。

  • WindowsCondition
package com.tianxia.springannotation.config.configCondition;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
 * 判斷操作系統(tǒng)是否是Linux系統(tǒng)
 * @author liqb
 * @date 2023-04-23 14:40
 **/
public class WindowsCondition implements Condition {
    /**
     * 匹配方法
     * @author liqb
     * @date 2023-04-23 12:57
     * @param context 判斷條件能使用的上下文(環(huán)境)
     * @param metadata 當(dāng)前標(biāo)注了@Conditional注解的注釋信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        if (property.contains("Windows")) {
            return true;
        }
        return false;
    }
}

配置類中使用@Conditional注解添加條件,添加該注解后的方法如下所示。

package com.tianxia.springannotation.config;
import com.tianxia.springannotation.config.configCondition.LinuxCondition;
import com.tianxia.springannotation.config.configCondition.WindowsCondition;
import com.tianxia.springannotation.entity.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
/**
 * 配置類
 * @author liqb
 * @date 2023-04-23 9:45
 **/
@Configuration
public class MainConfig02 {
    /**
     * 創(chuàng)建person實(shí)例
     * @author liqb
     * @date 2023-04-23 09:46
     * @return
     */
    @Bean("person02")
    //通過@Scope注解來指定該bean的作用范圍,也可以說成是調(diào)整作用域
    @Scope("prototype")
    public Person person() {
        System.out.println("給容器中添加咱們這個Person對象...");
        return new Person("liqb", 24);
    }
    /**
     * 創(chuàng)建person實(shí)例 名為bill
     * @author liqb
     * @date 2023-04-23 12:47
     * @return
     */
    @Bean("bill")
    @Conditional({WindowsCondition.class})
    public Person person01() {
        return new Person("Bill Gates", 62);
    }
    /**
     * 創(chuàng)建person實(shí)例 名為linus
     * @author liqb
     * @date 2023-04-23 12:47
     * @return
     */
    @Bean("linus")
    @Conditional({LinuxCondition.class})
    public Person person02() {
        return new Person("linus", 48);
    }
}

在運(yùn)行測試方法,輸出的結(jié)果信息如下所示:

輸出結(jié)果中不再含有名稱為linus的bean了,這說明程序中檢測到當(dāng)前操作系統(tǒng)為Windows 10之后,沒有向Spring容器中注冊名稱為linus的bean。

@Conditional注解也可以標(biāo)注在類上,標(biāo)注在類上的含義是:只有滿足了當(dāng)前條件,這個配置類中配置的所有bean注冊才能生效,也就是對配置類中的組件進(jìn)行統(tǒng)一設(shè)置。

package com.tianxia.springannotation.config;
import com.tianxia.springannotation.config.configCondition.LinuxCondition;
import com.tianxia.springannotation.config.configCondition.WindowsCondition;
import com.tianxia.springannotation.entity.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
/**
 * 配置類
 * @author liqb
 * @date 2023-04-23 9:45
 **/
@Configuration
// 滿足當(dāng)前條件,這個類中配置的所有bean注冊才能生效
@Conditional({LinuxCondition.class}) 
public class MainConfig02 {
    /**
     * 創(chuàng)建person實(shí)例
     * @author liqb
     * @date 2023-04-23 09:46
     * @return
     */
    @Bean("person02")
    //通過@Scope注解來指定該bean的作用范圍,也可以說成是調(diào)整作用域
    @Scope("prototype")
    public Person person() {
        System.out.println("給容器中添加咱們這個Person對象...");
        return new Person("liqb", 24);
    }
    /**
     * 創(chuàng)建person實(shí)例 名為bill
     * @author liqb
     * @date 2023-04-23 12:47
     * @return
     */
    @Bean("bill")
    @Conditional({WindowsCondition.class})
    public Person person01() {
        return new Person("Bill Gates", 62);
    }
    /**
     * 創(chuàng)建person實(shí)例 名為linus
     * @author liqb
     * @date 2023-04-23 12:47
     * @return
     */
    @Bean("linus")
    @Conditional({LinuxCondition.class})
    public Person person02() {
        return new Person("linus", 48);
    }
}

運(yùn)行測試方法之后,發(fā)現(xiàn)輸出的結(jié)果信息如下所示:

沒有任何bean的定義信息輸出,這是因?yàn)槌绦驒z測到了當(dāng)前操作系統(tǒng)為window,沒有向Spring容器中注冊任何bean的緣故導(dǎo)致的。

3.@Conditional的擴(kuò)展注解

@Conditional擴(kuò)展注解作用 (判斷是否滿足當(dāng)前指定條件)
@ConditionOnJava系統(tǒng)的Java版本是否符合要求
@ConditionOnBean容器中存在指定Bean
@ConditionOnMissingBean容器中不存在指定Bean
@ConditionOnExpression滿足SpEL表達(dá)式指定
@ConditionOnClass系統(tǒng)中有指定的類
@ConditionOnMissingClass系統(tǒng)中沒有指定的類
@ConditionOnSingleCandidate容器中只有一個指定的bean,或者這個bean是首選bean
@ConditionOnProperty系統(tǒng)中指定的屬性是否有指定的值
@ConditionOnResource類路徑下是否存在指定資源文件
@ConditionalOnWebApplication當(dāng)前是web環(huán)境
@ConditionalOnNoWebApplication當(dāng)前不是web環(huán)境
@ConditionalOnJndiJNDI存在指定項

總結(jié)

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java sleep()和wait()的區(qū)別點(diǎn)總結(jié)

    java sleep()和wait()的區(qū)別點(diǎn)總結(jié)

    在本篇文章里小編給大家整理了一篇關(guān)于java sleep()和wait()的區(qū)別的相關(guān)內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。
    2021-04-04
  • 深入理解Java虛擬機(jī)_動力節(jié)點(diǎn)Java學(xué)院整理

    深入理解Java虛擬機(jī)_動力節(jié)點(diǎn)Java學(xué)院整理

    虛擬機(jī)是一種抽象化的計算機(jī),通過在實(shí)際的計算機(jī)上模擬各種計算機(jī)功能來實(shí)現(xiàn)的,下面通過本文給大家分享Java虛擬機(jī)相關(guān)知識,感興趣的朋友一起看看吧
    2017-06-06
  • JAVA獲取Image的三種方式

    JAVA獲取Image的三種方式

    這篇文章主要介紹了JAVA獲取Image的三種方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • Python連接Java Socket服務(wù)端的實(shí)現(xiàn)方法

    Python連接Java Socket服務(wù)端的實(shí)現(xiàn)方法

    這篇文章主要介紹了Python連接Java Socket服務(wù)端的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • SpringBoot自定義全局異常處理器的問題總結(jié)

    SpringBoot自定義全局異常處理器的問題總結(jié)

    Springboot框架提供兩個注解幫助我們十分方便實(shí)現(xiàn)全局異常處理器以及自定義異常,處理器會優(yōu)先處理更具體的異常類型,如果沒有找到匹配的處理器,那么它會尋找處理更一般異常類型的處理器,本文介紹SpringBoot自定義全局異常處理器的問題,一起看看吧
    2024-01-01
  • java中匿名內(nèi)部類解讀分析

    java中匿名內(nèi)部類解讀分析

    本篇文章介紹了,java中匿名內(nèi)部類解讀分析。需要的朋友參考下
    2013-05-05
  • 教你在SpringBoot中管理多環(huán)境配置文件

    教你在SpringBoot中管理多環(huán)境配置文件

    在項目開發(fā)中,一般會分為開發(fā)環(huán)境,測試環(huán)境和生產(chǎn)環(huán)境.如果總是在一個文件中修修改改,難免會出現(xiàn)錯誤,尤其是在交接的過程中,一旦出現(xiàn)問題,輕則丟失績效,重則需要刪庫跑路.本文則帶大家詳細(xì)了解怎么管理多環(huán)境配置文件,需要的朋友可以參考下
    2021-05-05
  • hashCode方法的使用講解

    hashCode方法的使用講解

    有許多人學(xué)了很長時間的Java,但一直不明白hashCode方法的作用,我來解釋一下吧。
    2013-03-03
  • Mybatis-Plus3.2.0 MetaObjectHandler 無法進(jìn)行公共字段全局填充

    Mybatis-Plus3.2.0 MetaObjectHandler 無法進(jìn)行公共字段全局填充

    這篇文章主要介紹了Mybatis-Plus3.2.0 MetaObjectHandler 無法進(jìn)行公共字段全局填充,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • Java中try、catch的使用方法

    Java中try、catch的使用方法

    這篇文章主要介紹了Java中try、catch的使用方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06

最新評論

巴林左旗| 新河县| 南岸区| 木里| 酉阳| 务川| 灵武市| 西宁市| 淳化县| 大理市| 临夏县| 玛沁县| 旺苍县| 新郑市| 鄂尔多斯市| 望谟县| 桐柏县| 临漳县| 天峨县| 遂平县| 衢州市| 临洮县| 庆云县| 固原市| 平江县| 台南县| 旺苍县| 平谷区| 嘉祥县| 洛川县| 尉氏县| 达孜县| 海盐县| 资阳市| 密云县| 马鞍山市| 临洮县| 乌拉特中旗| 宝应县| 湘阴县| 定边县|