欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring筆記-@Order注解和Ordered接口解析

 更新時間:2022年08月17日 16:16:11   作者:那些年的代碼  
這篇文章主要介紹了Spring筆記-@Order注解和Ordered接口,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

@Order注解和Ordered接口

Order注解用于排序

public @interface Order {
?
? ? /**
? ? ?* The order value.
? ? ?* <p>Default is {@link Ordered#LOWEST_PRECEDENCE}.
? ? ?* @see Ordered#getOrder()
? ? ?*/
? ? int value() default Ordered.LOWEST_PRECEDENCE;
?
}

1.OrderUtils

Spring提供了OrderUtils來獲取Class的Order注解排序信息

擴展:Priority注解為javax擴展注解,功能與Order相同

public class OrderUtilsTests {
?
? ? @Test
? ? public void getSimpleOrder() {
? ? ? ? assertEquals(Integer.valueOf(50), OrderUtils.getOrder(SimpleOrder.class, null));
? ? }
?
? ? @Test
? ? public void getPriorityOrder() {
? ? ? ? assertEquals(Integer.valueOf(55), OrderUtils.getOrder(SimplePriority.class, null));
? ? }
?
? ? @Order(50)
? ? private static class SimpleOrder {}
?
? ? @Priority(55)
? ? private static class SimplePriority {}
}

2.Ordered接口

對象排序的另一種實現(xiàn)

public interface Ordered {
? ? int getOrder();
}

3.OrderComparator

使用OrderComparator來比較2個對象的排序順序

public final class OrderComparatorTests {
?
? ? private final OrderComparator comparator = new OrderComparator();
?
? ? @Test
? ? public void compareOrderedInstancesBefore() {
? ? ? ? assertEquals(-1, this.comparator.compare(
? ? ? ? ? ? ? ? new StubOrdered(100), new StubOrdered(2000)));
? ? }
?
? ? @Test
? ? public void compareOrderedInstancesSame() {
? ? ? ? assertEquals(0, this.comparator.compare(
? ? ? ? ? ? ? ? new StubOrdered(100), new StubOrdered(100)));
? ? }
?
? ? @Test
? ? public void compareOrderedInstancesAfter() {
? ? ? ? assertEquals(1, this.comparator.compare(
? ? ? ? ? ? ? ? new StubOrdered(982300), new StubOrdered(100)));
? ? }
?
? ? private static final class StubOrdered implements Ordered {
?
? ? ? ? private final int order;
?
? ? ? ? public StubOrdered(int order) {
? ? ? ? ? ? this.order = order;
? ? ? ? }
?
? ? ? ? @Override
? ? ? ? public int getOrder() {
? ? ? ? ? ? return this.order;
? ? ? ? }
? ? }
?
}

其內(nèi)部比較邏輯

return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
  • i1比i2小則返回-1
  • i1比i2大則返回1
  • i1等于i2則返回0

4.AnnotationAwareOrderComparator

AnnotationAwareOrderComparator繼承自O(shè)rderComparator

其可以同時處理對象實現(xiàn)Ordered接口或@Order注解

其提供了靜態(tài)方法sort,可以對List進行排序

public class AnnotationAwareOrderComparator extends OrderComparator {
}

測試代碼

public class AnnotationAwareOrderComparatorTests {
?
? ? @Test
? ? public void sortInstances() {
? ? ? ? List<Object> list = new ArrayList<>();
? ? ? ? list.add(new B());
? ? ? ? list.add(new A());
? ? ? ? AnnotationAwareOrderComparator.sort(list);
? ? ? ? assertTrue(list.get(0) instanceof A);
? ? ? ? assertTrue(list.get(1) instanceof B);
? ? }
?
? ? @Order(1)
? ? private static class A {
? ? }
?
? ? @Order(2)
? ? private static class B {
? ? }
}

5.Bean注冊順序

Demo2Config的對象將會先于Demo1Config初始化注冊

注意點:其構(gòu)造函數(shù)的初始化并不生效

@Configuration
@Order(2)
public class Demo1Config {
?
? ? public Demo1Config()
? ? {
? ? ? ? System.out.println("Demo1Config");
? ? }
?
? ? @Bean
? ? public Demo1Service demo1Service(){
? ? ? ? System.out.println("demo1config 加載了");
? ? ? ? return new Demo1Service();
? ? }
}
?
@Configuration
@Order(1)
public class Demo2Config {
?
? ? public Demo2Config()
? ? {
? ? ? ? System.out.println("Demo2Config");
? ? }
?
? ? @Bean
? ? public Demo2Service demo2Service(){
? ? ? ? System.out.println("demo2config 加載了");
? ? ? ? return new Demo2Service();
? ? }
}
?
public class Main {
? ? public static void main(String[] args) {
? ? ? ? AnnotationConfigApplicationContext context =
? ? ? ? ? ? ? ? new AnnotationConfigApplicationContext("core.annotation.order2");
? ? }
?
}

輸出的結(jié)果信息:

Demo1Config

Demo2Config

demo2config 加載了

demo1config 加載了

Spring的Orderd接口及@Order,@Primary,@Priority三個注解介紹

今天要來說一下Orderd接口以及@Order、@Primary、@Priority注解這幾個東西,原本只是想介紹一下@Order,但是這幾個有一定的關(guān)聯(lián),因此這里一起進行介紹。這幾個接口是用來排序,本文主要介紹用法,具體的比如Spring什么時候?qū)λ麄兣判虬?,后面在介紹Spring的處理過程的時候再介紹,還有怎么排序的這些比較好理解的也不介紹了。

1.如何發(fā)現(xiàn)Orderd接口及@Order、@Primary、@Priority

在前面文章說過要通過一些常用的注解以及在學(xué)習(xí)過程中不斷的發(fā)現(xiàn),因此這里我還是按我學(xué)習(xí)的思路介紹一下我是如何發(fā)現(xiàn)他們的。如果沒有一個發(fā)現(xiàn)以及理解的過程有時候可能會很難記住,就比如我之前專門了解了Spring相關(guān)的注解,并且去學(xué)習(xí)用法,但是不理解稍微一不用就忘記了。

首先自己創(chuàng)建一個測試類,創(chuàng)建AnnotationConfigApplicationContext實例。

?? ?@Test
?? ?public void test() {
?? ??? ?ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

進入AnnotationConfigApplicationContext構(gòu)造函數(shù)可以發(fā)現(xiàn)調(diào)用了無參構(gòu)造函數(shù),里面有個創(chuàng)建AnnotatedBeanDefinitionReader的步驟,Spring用BeanDefinition表示一個Bean,因此這個類也很容易理解就是與讀取注解Bean有關(guān)的類。

?? ?public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
?? ??? ?super(beanFactory);
?? ??? ?this.reader = new AnnotatedBeanDefinitionReader(this);
?? ??? ?this.scanner = new ClassPathBeanDefinitionScanner(this);
?? ?}

繼續(xù)進入可以看到AnnotatedBeanDefinitionReader的構(gòu)造函數(shù),最后一行表示將那些處理注解的基礎(chǔ)設(shè)施類添加到 DefaultListableBeanFactory中。進入這個方法中。

?? ?public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
?? ??? ?Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
?? ??? ?Assert.notNull(environment, "Environment must not be null");
?? ??? ?this.registry = registry;
?? ??? ?// 創(chuàng)建條件判斷者,后面用來進行條件注解的判斷,關(guān)聯(lián)@Conditional注解,@Conditional注解內(nèi)傳入的用于判斷的類要實現(xiàn)Condition接口的match方法
?? ??? ?this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);

?? ??? ?// 將那些處理注解的基礎(chǔ)設(shè)施類添加到 DefaultListableBeanFactory中
?? ??? ?AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
?? ?}

方法中有個判斷AnnotationAwareOrderComparator是否存在步驟,這個類從字面意思可以看出就是個比較器。

?? ?public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
?? ??? ??? ?BeanDefinitionRegistry registry, @Nullable Object source) {

?? ??? ?// 判斷BeanFactory是不是DefaultListableBeanFactory類型,如果不是需要進行轉(zhuǎn)換
?? ??? ?DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
?? ??? ?if (beanFactory != null) {
?? ??? ??? ?// beanFactory的依賴關(guān)系比較器,如果沒有AnnotationAwareOrderComparator這個比較器,就傳入全局默認靜態(tài)不可變的order比較器
?? ??? ??? ?if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
?? ??? ??? ??? ?beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
?? ??? ??? ?}

查看這個類的介紹可以看到這個類是OrderComparator的派生,OrderComparator是用來對Orderd或者@Order等內(nèi)部的值進行比較,內(nèi)部源碼我們不做介紹,就是獲取值然后進行數(shù)值的比較。這個類支持Ordered、@Order、@Priority,這些是我們今天要介紹的主要內(nèi)容了,@Primary初始看起來沒有關(guān)聯(lián),后面我們再介紹為什么會有他。

/**
?* {@code AnnotationAwareOrderComparator} is an extension of
?* {@link OrderComparator} that supports Spring's
?* {@link org.springframework.core.Ordered} interface as well as the
?* {@link Order @Order} and {@link javax.annotation.Priority @Priority}
?* annotations, with an order value provided by an {@code Ordered}
?* instance overriding a statically defined annotation value (if any).
?*
?* <p>Consult the Javadoc for {@link OrderComparator} for details on the
?* sort semantics for non-ordered objects.
?*
?* @author Juergen Hoeller
?* @author Oliver Gierke
?* @author Stephane Nicoll
?* @since 2.0.1
?* @see org.springframework.core.Ordered
?* @see org.springframework.core.annotation.Order
?* @see javax.annotation.Priority
?*/

public class AnnotationAwareOrderComparator extends OrderComparator {

2.Orderd、@Order、@Priority、@Primary

這一個接口和三個注解比較簡單,我粗略介紹一下,不做具體的介紹??偟膩碚f都是用來做bean加載的排序。

  • ①orderd接口,實現(xiàn)Oderd接口的話要實現(xiàn)int getOrder();這個方法,返回一個整數(shù)值,值越小優(yōu)先級越高。
  • ②@Order里面存儲了一個值,默認為Integer的最大值,同樣值越小優(yōu)先級越高。要注意@Order只能控制組件的加載順序,不能控制注入的優(yōu)先級。但是能控制List 里面存放的XXX的順序,原因是當(dāng)通過構(gòu)造函數(shù)或者方法參數(shù)注入進某個List時,Spring的DefaultListableBeanFactory類會在注入時調(diào)用AnnotationAwareOrderComparator.sort(listA)幫我們?nèi)ネ瓿筛鶕?jù)@Order或者Ordered接口序值排序。@Order更加適用于集合注入的排序。
  • ③@Priority與@Order類似,@Order是Spring提供的注解,@Priority是JSR 250標準,同樣是值越小優(yōu)先級越高。但是兩者還是有一定卻別,@Priority能夠控制組件的加載順序,因此@Priority側(cè)重于單個注入的優(yōu)先級排序。此外@Priority優(yōu)先級比@Order更高,兩者共存時優(yōu)先加載@Priority。
  • ④@Primary是優(yōu)先級最高的,如果同時有@Primary以及其他幾個的話,@Primary注解的Bean會優(yōu)先加載。

這個優(yōu)先級可以在Spring源碼中的DefaultListableBeanFactory類看出,從下面的代碼可以看到優(yōu)先確定Primary的,然后在根據(jù)權(quán)重來確定,Order與Priority只是不同規(guī)范定義的兩種注解,兩者效果是類似的。這里再額外說一下@Qualifier注解,如果beanName和@Qualifier一致,那么這個優(yōu)先級更高,有興趣的可以自己去源碼探索一下,后面文章也會詳細介紹@Qualifier這個注解。

/**
?? ? * Determine the autowire candidate in the given set of beans.
?? ? * <p>Looks for {@code @Primary} and {@code @Priority} (in that order).
?? ? * @param candidates a Map of candidate names and candidate instances
?? ? * that match the required type, as returned by {@link #findAutowireCandidates}
?? ? * @param descriptor the target dependency to match against
?? ? * @return the name of the autowire candidate, or {@code null} if none found
?? ? */
?? ?@Nullable
?? ?protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
?? ??? ?Class<?> requiredType = descriptor.getDependencyType();
?? ??? ?String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
?? ??? ?if (primaryCandidate != null) {
?? ??? ??? ?return primaryCandidate;
?? ??? ?}
?? ??? ?String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
?? ??? ?if (priorityCandidate != null) {
?? ??? ??? ?return priorityCandidate;
?? ??? ?}
?? ??? ?// Fallback
?? ??? ?for (Map.Entry<String, Object> entry : candidates.entrySet()) {
?? ??? ??? ?String candidateName = entry.getKey();
?? ??? ??? ?Object beanInstance = entry.getValue();
?? ??? ??? ?if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
?? ??? ??? ??? ??? ?matchesBeanName(candidateName, descriptor.getDependencyName())) {
?? ??? ??? ??? ?return candidateName;
?? ??? ??? ?}
?? ??? ?}
?? ??? ?return null;
?? ?}

3.測試

測試函數(shù)如下所示,只有簡單的兩行,創(chuàng)建Spring上下文獲取bean,調(diào)用s()方法。具體的實現(xiàn)看OrderTest類。

?? ?@Test
?? ?public void test4() {
?? ??? ?ApplicationContext applicationContext = new AnnotationConfigApplicationContext(OrderTest.class);
?? ??? ?((OrderTest)applicationContext.getBean("orderTest")).test.s();
?? ?}

①使用兩個@Order注解

如下所示,我們分別給Test1和Test2t設(shè)置@Order為3和2,執(zhí)行后拋出異常,原因是@Order不能控制注入的優(yōu)先級。

@Configuration
public class OrderTest {
?? ?public interface Test {
?? ??? ?void s();
?? ?}

?? ?@Service
?? ?@Order(3)
?? ?public class Test1 implements Test {
?? ??? ?@Override
?? ??? ?public void s() {
?? ??? ??? ?System.out.println(1);
?? ??? ?}
?? ?}

?? ?@Service
?? ?@Order(2)
?? ?public class Test2 implements Test {
?? ??? ?@Override
?? ??? ?public void s() {
?? ??? ??? ?System.out.println(2);
?? ??? ?}
?? ?}

?? ?@Autowired
?? ?public Test test;
}

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'orderTest': Unsatisfied dependency expressed through field 'test'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.huang.config.OrderTest$Test' available: expected single matching bean but found 2: com.huang.config.OrderTest$Test2,com.huang.config.OrderTest$Test1

②使用兩個注解以及一個@Primary注解

我們再上面基于給Test1添加@Primary,由于@Primary優(yōu)先級更高,因此可以控制注入的優(yōu)先級,所以 Test1的實例被注入了,輸出結(jié)果為1。

@Configuration
public class OrderTest {
?? ?public interface Test {
?? ??? ?void s();
?? ?}

?? ?@Service
?? ?@Order(3)
?? ?@Primary
?? ?public class Test1 implements Test {
?? ??? ?@Override
?? ??? ?public void s() {
?? ??? ??? ?System.out.println(1);
?? ??? ?}
?? ?}

?? ?@Service
?? ?@Order(2)
?? ?public class Test2 implements Test {
?? ??? ?@Override
?? ??? ?public void s() {
?? ??? ??? ?System.out.println(2);
?? ??? ?}
?? ?}

?? ?@Autowired
?? ?public Test test;
}

1

Process finished with exit code 0

③既有@Order,又有@Priority

既有@Order,又有@Priority時,可以看到雖然@Order的值更小,之前介紹值越小優(yōu)先級越高,但是由于@Priority優(yōu)先級更高,所以注入了Test1。

@Configuration
public class OrderTest {
?? ?public interface Test {
?? ??? ?void s();
?? ?}

?? ?@Service
?? ?@Priority(3)
?? ?public class Test1 implements Test {
?? ??? ?@Override
?? ??? ?public void s() {
?? ??? ??? ?System.out.println(1);
?? ??? ?}
?? ?}

?? ?@Service
?? ?@Order(2)
?? ?public class Test2 implements Test {
?? ??? ?@Override
?? ??? ?public void s() {
?? ??? ??? ?System.out.println(2);
?? ??? ?}
?? ?}

?? ?@Autowired
?? ?public Test test;
}

1

Process finished with exit code 0

④兩個@Priority注解

兩個@Priority注解同時存在時,值越小優(yōu)先級越高,因此優(yōu)先注入的是Test2。

@Configuration
public class OrderTest {
?? ?public interface Test {
?? ??? ?void s();
?? ?}

?? ?@Service
?? ?@Priority(4)
?? ?public class Test1 implements Test {
?? ??? ?@Override
?? ??? ?public void s() {
?? ??? ??? ?System.out.println(1);
?? ??? ?}
?? ?}

?? ?@Service
?? ?@Priority(3)
?? ?public class Test2 implements Test {
?? ??? ?@Override
?? ??? ?public void s() {
?? ??? ??? ?System.out.println(2);
?? ??? ?}
?? ?}

?? ?@Autowired
?? ?public Test test;
}

2

Process finished with exit code 0

⑤使用@Order控制集合注入

修改要注入的為Test集合

@Configuration
public class OrderTest {
?? ?public interface Test {
?? ??? ?void s();
?? ?}

?? ?@Service
?? ?@Order(2)
?? ?public class Test1 implements Test {
?? ??? ?@Override
?? ??? ?public void s() {
?? ??? ??? ?System.out.println(1);
?? ??? ?}
?? ?}

?? ?@Service
?? ?@Order(1)
?? ?public class Test2 implements Test {
?? ??? ?@Override
?? ??? ?public void s() {
?? ??? ??? ?System.out.println(2);
?? ??? ?}
?? ?}

?? ?@Autowired
?? ?public List<Test> testList;
}

修改測試代碼

?? ?@Test
?? ?public void test4() {
?? ??? ?ApplicationContext applicationContext = new AnnotationConfigApplicationContext(OrderTest.class);
?? ??? ?((OrderTest)applicationContext.getBean("orderTest")).testList.get(0).s();
?? ?}

執(zhí)行結(jié)果如下所示,可以看到@Order值小的,優(yōu)先級更高,在集合的前邊。

2

Process finished with exit code 0

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

相關(guān)文章

  • 詳解Java?List中五種常見實現(xiàn)類的使用

    詳解Java?List中五種常見實現(xiàn)類的使用

    Java中提供了非常多的使用的List實現(xiàn)類,本文將重點介紹一下常見的五種實現(xiàn)類以及他們的應(yīng)用場景,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-10-10
  • spring mvc 讀取xml文件數(shù)據(jù)庫配置參數(shù)的方法

    spring mvc 讀取xml文件數(shù)據(jù)庫配置參數(shù)的方法

    下面小編就為大家?guī)硪黄猻pring mvc 讀取xml文件數(shù)據(jù)庫配置參數(shù)的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • maven打包web項目時同時打包為war和jar文件的方法

    maven打包web項目時同時打包為war和jar文件的方法

    本篇文章主要介紹了maven打包web項目時同時打包為war和jar文件的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • 解決springboot 啟動找不到主類的問題

    解決springboot 啟動找不到主類的問題

    這篇文章主要介紹了解決springboot 啟動找不到主類的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Idea開發(fā)工具之SpringBoot整合JSP的過程

    Idea開發(fā)工具之SpringBoot整合JSP的過程

    最近在學(xué)習(xí)SpringBoot,看到SpringBoot整合jsp,順帶記錄一下。本文通過圖文實例相結(jié)合給大家講解SpringBoot整合JSP的過程,感興趣的朋友一起看看吧
    2021-09-09
  • Java彈簧布局管理器使用方法詳解

    Java彈簧布局管理器使用方法詳解

    這篇文章主要介紹了Java彈簧布局管理器使用方法詳解,需要的朋友可以參考下
    2017-09-09
  • java基于netty NIO的簡單聊天室的實現(xiàn)

    java基于netty NIO的簡單聊天室的實現(xiàn)

    這篇文章主要介紹了java基于netty NIO的簡單聊天室的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Maven在Java8下如何忽略Javadoc的編譯錯誤詳解

    Maven在Java8下如何忽略Javadoc的編譯錯誤詳解

    這篇文章主要給大家介紹了關(guān)于Maven在Java8下如何忽略Javadoc的編譯錯誤的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-08-08
  • springBoot整合rabbitMQ的方法詳解

    springBoot整合rabbitMQ的方法詳解

    這篇文章主要介紹了springBoot整合rabbitMQ的方法詳解,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • Spring五大類注解讀取存儲Bean對象的方法

    Spring五大類注解讀取存儲Bean對象的方法

    這篇文章主要介紹了Spring五大類注解讀取存儲Bean對象,本文通過示例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-09-09

最新評論