首頁 > 軟體

淺析SpringBoot2底層註解@Conditional@ImportResource

2022-05-28 14:00:15

SpringBoot2底層註解

一、@ImportResource

@Conditional註解,是根據條件進行裝配。滿足了 Conditional 指定的條件,就進行元件的注入。

另外@Conditional是個根註解,在idea裡使用 ctrl+H 可以開啟它的結構。

可以看到有許多的派生註解,每個註解都代表著一種功能。比如:

@ConditionalOnBean:當容器中存在指定的元件,才會做某些事情。

@ConditionalOnMissingBean:當容器中沒有指定的元件,才會做某些事情。

@ConditionalOnClass:當容器中存在指定的類。

@ConditionalOnMissingClass:當容器中不存在指定的類。

@ConditionalOnResource:專案類路徑裡存在某個資源的時候。

@ConditionalOnJava:當是指定的 java 版本號。

@ConditionalOnWebApplication:當應用是一個 web 應用的時候。

@ConditionalOnNotWebApplication:當應用不是一個 web 應用的時候。

@ConditionalOnProperty:當組態檔裡存在指定屬性的時候。

範例

以@ConditionalOnBean為例,演示一下用法。

還是看一下之前 MyConfig 類中的方法:

@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = true)
public class MyConfig {
    @Bean("user1")
    public User user01(){
        User pingguo = new User("pingguo",20);
        pingguo.setPet(tomcatPet());
        return pingguo;
    }
//    @Bean("pet1")
    public Pet tomcatPet(){
        return new Pet("tomcat");
    }
}

在這裡,我把pet1這個元件給註釋掉,現在tomcatPet()其實就是個普通的類方法。

先嚐試在主執行類的 main 方法裡獲取一下 這 2 個 元件:

@SpringBootApplication(scanBasePackages = "com.pingguo")
public class MainApplication {
    public static void main(String[] args) {
        // 返回IOC容器
        final ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
        boolean tomcatPet = run.containsBean("pet1");
        System.out.println("容器中存在 pet1 的元件:" + tomcatPet);
        boolean user1 = run.containsBean("user1");
        System.out.println("容器中存在 user1 的元件:" + user1);
    }
}

執行一下,檢視結果:

果然,是不存在pet1元件的,因為@bean這個註解被我註釋掉了。

OK,現在我有個需求,因為user1元件依賴pet1元件,如果沒有pet1,我希望user1元件也直接別註冊了。

這時候就可以使用@ConditionalOnBean註解來完成。

@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = true)
public class MyConfig {
    @ConditionalOnBean(name = "pet1")
    @Bean("user1")
    public User user01(){
        User pingguo = new User("pingguo",20);
        pingguo.setPet(tomcatPet());
        return pingguo;
    }
//    @Bean("pet1")
    public Pet tomcatPet(){
        return new Pet("tomcat");
    }
}

在 user1元件上加上@ConditionalOnBean(name = "pet1"),當沒有pet1元件,就不註冊user1元件。

現在再執行 main 方法測試一下,應該都是 false,2個元件都不存在。

作用在類上

@ConditionalOnBean(name = "pet1")如果我放在類上:

@ConditionalOnBean(name = "pet1") // 放在類上
@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = true)
public class MyConfig {
    @Bean("user1")
    public User user01(){
        User pingguo = new User("pingguo",20);
        pingguo.setPet(tomcatPet());
        return pingguo;
    }
    @Bean("pet22")
    public Pet tomcatPet(){
        return new Pet("tomcat");
    }
}

現在就表示,當存在pet1元件的時候,這個類下面的所有才會生效。

這裡我改了下面的元件註冊變成pet22,也就是說當存在pet1元件的時候,就會註冊user1和pet22。

在 main 方法裡增加列印pet22,檢視是否存在:

... ...
    boolean pet22 = run.containsBean("pet22");
    System.out.println("容器中存在 pet22 的元件:" + pet22);
... ...

執行一下:

因為不存在pet1這個元件,所有MyConfig類下面的2個元件user1和pet22的註冊都不生效。

二、@ImportResource

@ImportResource註解是用來匯入資源。

比如,之前我們可能會在 spring 組態檔中寫非常多的元件匯入:

... ...
    <bean id="haha" class="com.pingguo.boot.bean.User">
        <property name="name" value="pingguo"></property>
        <property name="age" value="20"></property>
    </bean>
    <bean id="hehe" class="com.pingguo.boot.bean.User">
        <property name="name" value="tomcat"></property>
    </bean>

這裡只是demo,實際工程中可能會存在很多 bean,如果想要逐個遷移成註解的方式,會很麻煩。

但是現在容器裡又是沒有這些元件的,在 main 方法裡輸出測試一下:

boolean haha = run.containsBean("haha");
    System.out.println("容器中存在 haha 的元件:" + haha);
    boolean hehe = run.containsBean("hehe");
    System.out.println("容器中存在 hehe 的元件:" + hehe);

因為這些元件宣告在 xml 裡,springboot 也並不知道這些是幹嘛的。

這時候就可以使用@ImportResource來匯入這些元件:

//@ConditionalOnBean(name = "pet1")
@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = true)
@ImportResource("classpath:beans.xml")  //組態檔的類路徑 
public class MyConfig {
    @Bean("user1")
    public User user01(){
        User pingguo = new User("pingguo",20);
        pingguo.setPet(tomcatPet());
        return pingguo;
    }
    @Bean("pet22")
    public Pet tomcatPet(){
        return new Pet("tomcat");
    }
}

這個時候再執行測試一下:

xml 組態檔裡的元件被成功解析註冊到了容器中。

以上就是淺析SpringBoot2底層註解@Conditional@ImportResource的詳細內容,更多關於SpringBoot2底層註解的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com