中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringBoot中Bean的搭建方法和加載順序的錯誤姿勢說明

發布時間:2021-09-03 18:59:38 來源:億速云 閱讀:109 作者:chen 欄目:大數據

本篇內容介紹了“SpringBoot中Bean的搭建方法和加載順序的錯誤姿勢說明”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

I. 環境搭建

創建一個 maven 項目,pom 文件如下(具體的項目代碼,可以在文末獲取)

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.7</version>
    <relativePath/> <!-- lookup parent from update -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </pluginManagement>
</build>
<repositories>
    <repository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>https://repo.spring.io/milestone</url>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>

II. 錯誤姿勢

下面我們會介紹兩種典型注解的錯誤使用姿勢,一個@Order,一個@AutoConfigureOrder

I. @Order

err.case1: 類上添加 Order 注解

一種常見的錯誤觀點是在類上添加這個 Order 注解,就可以指定 bean 之間的初始化順序,order 值越小,則優先級越高,接下來我們實際測試一下,是否如此

我們創建兩個 DemoBean, 指定不同的 Order 順序

@Order(4)
@Component
public class BaseDemo1 {
    private String name = "base demo 1";

    public BaseDemo1() {
        System.out.println(name);
    }
}

@Order(3)
@Component
public class BaseDemo2 {
    private String name = "base demo 2";

    public BaseDemo2() {
        System.out.println(name);
    }
}

根據前面的觀點,orde 值小的優先級高,那么 BaseDemo2 應該先被初始化,實際測試一下,輸出如下

SpringBoot中Bean的搭建方法和加載順序的錯誤姿勢說明

err.case2: 配置類中 Bean 聲明方法上添加@Order

Bean 除了上面的自動掃描之外,還有一種方式就是通過@Bean注解,下面我們演示一下在配置類中指定 bean 加載順序的錯誤 case

同樣我們新建兩個測試 bean

public class BaseDemo3 {
    private String name = "base demo 3";

    public BaseDemo3() {
        System.out.println(name);
    }
}

public class BaseDemo4 {
    private String name = "base demo 4";

    public BaseDemo4() {
        System.out.println(name);
    }
}

接下來在配置類中定義 bean

@Configuration
public class ErrorDemoAutoConf {
    @Order(2)
    @Bean
    public BaseDemo3 baseDemo3() {
        return new BaseDemo3();
    }

    @Order(1)
    @Bean
    public BaseDemo4 baseDemo4() {
        return new BaseDemo4();
    }
}

同樣的,如果@Order注解有效,那么BaseDemo4應該先被初始化

SpringBoot中Bean的搭建方法和加載順序的錯誤姿勢說明

從上面的實際測試輸出可以看出,@Order 注解在上面的方式中也不生效,如果有興趣的同學可以試一下,將上面配置類中的兩個方法的順序顛倒一下,會發現BaseDemo4先加載

err.case3: @Order 注解修飾配置類

這也是一種常見的錯誤 case,認為@Order 注解是用來指定配置類的加載順序的,然而真的是這樣么?

我們創建兩個測試的配置類

@Order(1)
@Configuration
public class AConf {
    public AConf() {
        System.out.println("AConf init!");
    }
}

@Order(0)
@Configuration
public class BConf {
    public BConf() {
        System.out.println("BConf init");
    }
}

如果@Order 注解生效,那么 BConf 配置類會優先初始化,那么我們實測一下 SpringBoot中Bean的搭建方法和加載順序的錯誤姿勢說明

從上面的結果可以看出,并不是 BConf 先被加載;當然這種使用姿勢,實際上和第一種錯誤 case,并沒有什么區別,配置類也是 bean,前面不生效,這里當然也不會生效

那么是不是我們的理解不對導致的呢,實際上這個@Order放在配置類上之后,是這個配置類中定義的 Bean 的優先于另一個配置類中定義的 Bean 呢?

同樣的我們測試下這種 case,我們定義三個 bean,兩個 conf

public class Demo1 {
    private String name = "conf demo bean 1";

    public Demo1() {
        System.out.println(name);
    }
}

public class Demo2 {
    private String name = "conf demo bean 2";

    public Demo2() {
        System.out.println(name);
    }
}

public class Demo3 {
    private String name = "conf demo bean 3";

    public Demo3() {
        System.out.println(name);
    }
}

然后我們將 Demo1, Demo3 放在一個配置中,Demo2 放在另外一個配置中

@Order(2)
@Configuration
public class AConf1 {
    @Bean
    public Demo1 demo1() {
        return new Demo1();
    }

    @Bean
    public Demo3 demo3() {
        return new Demo3();
    }
}

@Order(1)
@Configuration
public class BConf1 {

    @Bean
    public Demo2 demo2() {
        return new Demo2();
    }
}

如果@Order 注解實際上控制的是配置類中 Bean 的加載順序,那么 BConf1 中的 Bean 應該優先加載,也就是說 Demo2 會優先于 Demo1, Demo3,實際測試一下,輸出如

SpringBoot中Bean的搭建方法和加載順序的錯誤姿勢說明

上面的輸出結果和我們預期的并不一樣,所以@Order注解來決定配置類的順序也是不對的

2. @AutoConfigureOrder

從命名來看,這個注解是用來指定配置類的順序的,然而對于這個注解的錯誤使用也是非常多的,而大多的錯誤使用在于沒有真正的了解到它的使用場景

接下來我們來演示一下錯誤的使用 case

在工程內新建兩個配置類,直接使用注解

@Configuration
@AutoConfigureOrder(1)
public class AConf2 {
    public AConf2() {
        System.out.println("A Conf2 init!");
    }
}

@Configuration
@AutoConfigureOrder(-1)
public class BConf2 {
    public BConf2() {
        System.out.println("B conf2 init!");
    }
}

當注解生效時,BConf 會優先級加載

SpringBoot中Bean的搭建方法和加載順序的錯誤姿勢說明

從輸出結果來看,和我們預期的不一樣;那么這個注解是不是作用于配置類中的 Bean 的順序,而不是配置類本身呢?

同樣的我們設計一個 case 驗證一下

public class DemoA {
    private String name = "conf demo bean A";

    public DemoA() {
        System.out.println(name);
    }
}

public class DemoB {
    private String name = "conf demo bean B";

    public DemoB() {
        System.out.println(name);
    }
}

public class DemoC {
    private String name = "conf demo bean C";

    public DemoC() {
        System.out.println(name);
    }
}

對應的配置類

@Configuration
@AutoConfigureOrder(1)
public class AConf3 {
    @Bean
    public DemoA demoA() {
        return new DemoA();
    }

    @Bean
    public DemoC demoC() {
        return new DemoC();
    }
}

@Configuration
@AutoConfigureOrder(-1)
public class BConf3 {

    @Bean
    public DemoB demoB() {
        return new DemoB();
    }
}

如果 DemoB 后被加載,則說明上面的觀點是錯誤的,實測結果如下

SpringBoot中Bean的搭建方法和加載順序的錯誤姿勢說明

所以問題來了,@AutoConfigureOrder這個注解并不能指定配置類的順序,還叫這個名,干啥?存粹是誤導人不是!!!

接下來我們看一下@Order@AutoConfigureOrder的正確使用方式

III. 使用說明

1. @Order

先看一下這個注解的官方注釋

{@code @Order} defines the sort order for an annotated component. Since Spring 4.0, annotation-based ordering is supported for many kinds of components in Spring, even for collection injection where the order values of the target components are taken into account (either from their target class or from their {@code @Bean} method). While such order values may influence priorities at injection points, please be aware that they do not influence singleton startup order which is an orthogonal concern determined by dependency relationships and {@code @DependsOn} declarations (influencing a runtime-determined dependency graph).

最開始 Order 注解用于切面的優先級指定;在 4.0 之后對它的功能進行了增強,支持集合的注入時,指定集合中 bean 的順序

并且特別指出了,它對于但實例的 bean 之間的順序,沒有任何影響;這句話根據我們上面的測試也可以驗證

接下來我們需要看一下通過@Order 注解來注入集合時,指定順序的場景

首先我們定義兩個 Bean 實現同一個接口,并添加上@Order注解

public interface IBean {
}

@Order(2)
@Component
public class AnoBean1 implements IBean {

    private String name = "ano order bean 1";

    public AnoBean1() {
        System.out.println(name);
    }
}

@Order(1)
@Component
public class AnoBean2 implements IBean {

    private String name = "ano order bean 2";

    public AnoBean2() {
        System.out.println(name);
    }
}

然后再一個測試 bean 中,注入IBean的列表,我們需要測試這個列表中的 Bean 的順序是否和我們定義的@Order規則一致

@Component
public class AnoTestBean {

    public AnoTestBean(List<IBean> anoBeanList) {
        for (IBean bean : anoBeanList) {
            System.out.println("in ano testBean: " + bean.getClass().getName());
        }
    }
}

根據我們的預期, anoBeanList 集合中,anoBean2 應該在前面

SpringBoot中Bean的搭建方法和加載順序的錯誤姿勢說明

根據上面的輸出,也可以看出列表中的順序和我們預期的一致,并且 AnoOrderBean1AnoOrderBean2 的加載順序和注解沒有關系

2. @AutoConfigureOrder

這個注解用來指定配置文件的加載順序,然而前面的測試中并沒有生效,那么正確的使用姿勢是怎樣的呢?

@AutoConfigureOrder適用于外部依賴的包中 AutoConfig 的順序,而不能用來指定本包內的順序

為了驗證上面的說法,我們再次新建兩個工程,并指定自動配置類的順序

工程一配置如下:

@AutoConfigureOrder(1)
@Configuration
@ComponentScan(value = {"com.git.hui.boot.order.addition"})
public class AdditionOrderConf {
    public AdditionOrderConf() {
        System.out.println("additionOrderConf init!!!");
    }
}

注意自動配置類如要被正確加載,需要在工程的 /META-INF/spring.factories文件中定義

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.git.hui.boot.order.addition.AdditionOrderConf

工程二的配置如下:

@Configuration
@AutoConfigureOrder(-1)
@ComponentScan("com.git.hui.boot.order.addition2")
public class AdditionOrderConf2 {

    public AdditionOrderConf2() {
        System.out.println("additionOrderConf2 init!!!");
    }
}

然后我們在項目內部添加一個配置

@AutoConfigureOrder(10)
@Configuration
public class OrderConf {
    public OrderConf() {
        System.out.println("inner order conf init!!!");
    }
}

因為注解適用于外部依賴包中的自動配置類的順序,所以上面三個配置類中,正確的話 AdditionOrderConf2 在 AdditionOrderConf1 之前;而 OrderConf 并不會收到注解的影響,默認環境下,內部定義的配置類會優于外部依賴,從下面的輸出也可以佐證我們說明(當然為了驗證確實如次,還應該調整下兩個外部工程配置類的順序,并觀察下加載順序是否隨之改變,我們這里省略掉了)

SpringBoot中Bean的搭建方法和加載順序的錯誤姿勢說明

“SpringBoot中Bean的搭建方法和加載順序的錯誤姿勢說明”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

应城市| 石泉县| 石楼县| 呼玛县| 合肥市| 鄯善县| 荔波县| 东丰县| 凤冈县| 福鼎市| 文水县| 光山县| 汪清县| 雅安市| 扎兰屯市| 留坝县| 泗水县| 聂荣县| 濮阳市| 松潘县| 正蓝旗| 辽源市| 灵丘县| 方山县| 靖州| 巴林左旗| 吉林省| 临猗县| 阳高县| 绥阳县| 远安县| 孟村| 库伦旗| 龙里县| 吉首市| 镇赉县| 自治县| 龙游县| 鲁山县| 武清区| 政和县|