您好,登錄后才能下訂單哦!
這篇“Spring的@Order注解和Ordered接口怎么應(yīng)用”文章的知識(shí)點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來(lái)看看這篇“Spring的@Order注解和Ordered接口怎么應(yīng)用”文章吧。
Order注解用于排序
public @interface Order { /** * The order value. * <p>Default is {@link Ordered#LOWEST_PRECEDENCE}. * @see Ordered#getOrder() */ int value() default Ordered.LOWEST_PRECEDENCE; }
Spring提供了OrderUtils來(lái)獲取Class的Order注解排序信息
擴(kuò)展:Priority注解為javax擴(kuò)展注解,功能與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 {} }
對(duì)象排序的另一種實(shí)現(xiàn)
public interface Ordered { int getOrder(); }
使用OrderComparator來(lái)比較2個(gè)對(duì)象的排序順序
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
AnnotationAwareOrderComparator繼承自O(shè)rderComparator
其可以同時(shí)處理對(duì)象實(shí)現(xiàn)Ordered接口或@Order注解
其提供了靜態(tài)方法sort,可以對(duì)List進(jìn)行排序
public class AnnotationAwareOrderComparator extends OrderComparator { }
測(cè)試代碼
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 { } }
Demo2Config的對(duì)象將會(huì)先于Demo1Config初始化注冊(cè)
注意點(diǎn):其構(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 加載了
在前面文章說(shuō)過(guò)要通過(guò)一些常用的注解以及在學(xué)習(xí)過(guò)程中不斷的發(fā)現(xiàn),因此這里我還是按我學(xué)習(xí)的思路介紹一下我是如何發(fā)現(xiàn)他們的。如果沒(méi)有一個(gè)發(fā)現(xiàn)以及理解的過(guò)程有時(shí)候可能會(huì)很難記住,就比如我之前專(zhuān)門(mén)了解了Spring相關(guān)的注解,并且去學(xué)習(xí)用法,但是不理解稍微一不用就忘記了。
首先自己創(chuàng)建一個(gè)測(cè)試類(lèi),創(chuàng)建AnnotationConfigApplicationContext實(shí)例。
@Test public void test() { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
進(jìn)入AnnotationConfigApplicationContext構(gòu)造函數(shù)可以發(fā)現(xiàn)調(diào)用了無(wú)參構(gòu)造函數(shù),里面有個(gè)創(chuàng)建AnnotatedBeanDefinitionReader的步驟,Spring用BeanDefinition表示一個(gè)Bean,因此這個(gè)類(lèi)也很容易理解就是與讀取注解Bean有關(guān)的類(lèi)。
public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) { super(beanFactory); this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); }
繼續(xù)進(jìn)入可以看到AnnotatedBeanDefinitionReader的構(gòu)造函數(shù),最后一行表示將那些處理注解的基礎(chǔ)設(shè)施類(lèi)添加到 DefaultListableBeanFactory中。進(jìn)入這個(gè)方法中。
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)建條件判斷者,后面用來(lái)進(jìn)行條件注解的判斷,關(guān)聯(lián)@Conditional注解,@Conditional注解內(nèi)傳入的用于判斷的類(lèi)要實(shí)現(xiàn)Condition接口的match方法 this.conditionEvaluator = new ConditionEvaluator(registry, environment, null); // 將那些處理注解的基礎(chǔ)設(shè)施類(lèi)添加到 DefaultListableBeanFactory中 AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); }
方法中有個(gè)判斷AnnotationAwareOrderComparator是否存在步驟,這個(gè)類(lèi)從字面意思可以看出就是個(gè)比較器。
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) { // 判斷BeanFactory是不是DefaultListableBeanFactory類(lèi)型,如果不是需要進(jìn)行轉(zhuǎn)換 DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); if (beanFactory != null) { // beanFactory的依賴(lài)關(guān)系比較器,如果沒(méi)有AnnotationAwareOrderComparator這個(gè)比較器,就傳入全局默認(rèn)靜態(tài)不可變的order比較器 if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); }
查看這個(gè)類(lèi)的介紹可以看到這個(gè)類(lèi)是OrderComparator的派生,OrderComparator是用來(lái)對(duì)Orderd或者@Order等內(nèi)部的值進(jìn)行比較,內(nèi)部源碼我們不做介紹,就是獲取值然后進(jìn)行數(shù)值的比較。這個(gè)類(lèi)支持Ordered、@Order、@Priority,這些是我們今天要介紹的主要內(nèi)容了,@Primary初始看起來(lái)沒(méi)有關(guān)聯(lián),后面我們?cè)俳榻B為什么會(huì)有他。
/** * {@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 {
這一個(gè)接口和三個(gè)注解比較簡(jiǎn)單,我粗略介紹一下,不做具體的介紹??偟膩?lái)說(shuō)都是用來(lái)做bean加載的排序。
①orderd接口,實(shí)現(xiàn)Oderd接口的話要實(shí)現(xiàn)int getOrder();這個(gè)方法,返回一個(gè)整數(shù)值,值越小優(yōu)先級(jí)越高。
②@Order里面存儲(chǔ)了一個(gè)值,默認(rèn)為Integer的最大值,同樣值越小優(yōu)先級(jí)越高。要注意@Order只能控制組件的加載順序,不能控制注入的優(yōu)先級(jí)。但是能控制List 里面存放的XXX的順序,原因是當(dāng)通過(guò)構(gòu)造函數(shù)或者方法參數(shù)注入進(jìn)某個(gè)List時(shí),Spring的DefaultListableBeanFactory類(lèi)會(huì)在注入時(shí)調(diào)用AnnotationAwareOrderComparator.sort(listA)幫我們?nèi)ネ瓿筛鶕?jù)@Order或者Ordered接口序值排序。@Order更加適用于集合注入的排序。
③@Priority與@Order類(lèi)似,@Order是Spring提供的注解,@Priority是JSR 250標(biāo)準(zhǔn),同樣是值越小優(yōu)先級(jí)越高。但是兩者還是有一定卻別,@Priority能夠控制組件的加載順序,因此@Priority側(cè)重于單個(gè)注入的優(yōu)先級(jí)排序。此外@Priority優(yōu)先級(jí)比@Order更高,兩者共存時(shí)優(yōu)先加載@Priority。
④@Primary是優(yōu)先級(jí)最高的,如果同時(shí)有@Primary以及其他幾個(gè)的話,@Primary注解的Bean會(huì)優(yōu)先加載。
這個(gè)優(yōu)先級(jí)可以在Spring源碼中的DefaultListableBeanFactory類(lèi)看出,從下面的代碼可以看到優(yōu)先確定Primary的,然后在根據(jù)權(quán)重來(lái)確定,Order與Priority只是不同規(guī)范定義的兩種注解,兩者效果是類(lèi)似的。這里再額外說(shuō)一下@Qualifier注解,如果beanName和@Qualifier一致,那么這個(gè)優(yōu)先級(jí)更高,有興趣的可以自己去源碼探索一下。
/** * 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; }
測(cè)試函數(shù)如下所示,只有簡(jiǎn)單的兩行,創(chuàng)建Spring上下文獲取bean,調(diào)用s()方法。具體的實(shí)現(xiàn)看OrderTest類(lèi)。
@Test public void test4() { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(OrderTest.class); ((OrderTest)applicationContext.getBean("orderTest")).test.s(); }
①使用兩個(gè)@Order注解
如下所示,我們分別給Test1和Test2t設(shè)置@Order為3和2,執(zhí)行后拋出異常,原因是@Order不能控制注入的優(yōu)先級(jí)。
@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
②使用兩個(gè)注解以及一個(gè)@Primary注解
我們?cè)偕厦婊诮oTest1添加@Primary,由于@Primary優(yōu)先級(jí)更高,因此可以控制注入的優(yōu)先級(jí),所以 Test1的實(shí)例被注入了,輸出結(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時(shí),可以看到雖然@Order的值更小,之前介紹值越小優(yōu)先級(jí)越高,但是由于@Priority優(yōu)先級(jí)更高,所以注入了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
④兩個(gè)@Priority注解
兩個(gè)@Priority注解同時(shí)存在時(shí),值越小優(yōu)先級(jí)越高,因此優(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控制集合注入
修改要注入的為T(mén)est集合
@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; }
修改測(cè)試代碼
@Test public void test4() { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(OrderTest.class); ((OrderTest)applicationContext.getBean("orderTest")).testList.get(0).s(); }
執(zhí)行結(jié)果如下所示,可以看到@Order值小的,優(yōu)先級(jí)更高,在集合的前邊。
2
Process finished with exit code 0
以上就是關(guān)于“Spring的@Order注解和Ordered接口怎么應(yīng)用”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對(duì)大家有幫助,若想了解更多相關(guān)的知識(shí)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。