在Spring 3.1中,有一種方法可以自動填充類型化的List,這在您想在代碼中稍微進行去耦和清理時非常方便。
為了向您展示它是如何工作的,我將實現一個簡單的責任鏈,該責任鏈將為通過的用戶打印一些問候。
讓我們從我們擁有的(唯一的)域類(用戶)開始:
package com.marco.springchain;
public class User {private final String name;private final char gender;public User(String name, char gender) {super();this.name = name;this.gender = gender;}public String getName() {return name;}public char getGender() {return gender;}
}
然后,我們創建一個接口,該接口定義要在鏈中使用的命令對象的類型:
package com.marco.springchain;
public interface Printer {void print(User user);
}
這是Printer實現的通用類(模板)。
org.springframework.core.Ordered
用于告訴AnnotationAwareOrderComparator我們希望如何對List進行排序。
如果不需要您的鏈來具有執行順序,則無需實現Ordered接口并重寫getOrder方法。
還要注意,這個抽象類返回Ordered.LOWEST_PRECEDENCE
,這是因為我希望一些打印機命令僅在鏈的末尾運行,并且我不在乎它們的執行順序(我保證,以后一切都會更清楚!)。
GenericPrinter
這是我們的第一個真正的打印機命令。 我希望它在鏈中具有絕對優先級,因此順序為HIGHEST_PRECEDENCE
。
package com.marco.springchain;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
@Component
public class HelloPrinter extends GenericPrinter {private static final String GREETING = 'Hello';@Overrideprotected String getGreeting() {return GREETING;}@Overridepublic int getOrder() {return Ordered.HIGHEST_PRECEDENCE;}
}
WelcomePrinter
將作為第一個命令執行( 在高優先級命令之后 )。
package com.marco.springchain;
import org.springframework.stereotype.Component;
@Component
public class WelcomePrinter extends GenericPrinter {private static final String GREETING = 'Welcome to the autowired chain';@Overrideprotected String getGreeting() {return GREETING;}@Overridepublic int getOrder() {return 1;}
}
GoodbyePrinter
將作為第二個命令執行
package com.marco.springchain;
import org.springframework.stereotype.Component;
@Component
public class GoodbyePrinter extends GenericPrinter {private static final String GREETING = 'Goodbye';@Overrideprotected String getGreeting() {return GREETING;}@Overridepublic int getOrder() {return 2;}
}
這兩個命令需要在其他命令之后執行,但是我不在乎它們的特定順序,因此我不會覆蓋getOrder方法,而讓GenericPrinter Ordered.LOWEST_PRECEDENCE
為這兩個命令返回Ordered.LOWEST_PRECEDENCE
。
package com.marco.springchain;
import org.springframework.stereotype.Component;
@Component
public class CleaningMemoryPrinter extends GenericPrinter {private static final String GREETING = 'Cleaning memory after';@Overrideprotected String getGreeting() {return GREETING;}
}
package com.marco.springchain;
import org.springframework.stereotype.Component;
@Component
public class CleaningSpacePrinter extends GenericPrinter {private static final String GREETING = 'Cleaning space after';@Overrideprotected String getGreeting() {return GREETING;}
}
這是鏈上下文。
Spring將掃描(請參閱spring-config.xml)配置文件中指定的包,它將看到類型化的( List<Printer>
)列表,并且它將使用實現該類型的任何@Component
的實例填充該列表。打印機。
為了對List進行排序,我們使用AnnotationAwareOrderComparator.INSTANCE
,它使用getOrder方法對List進行重新排序( 值最低的對象具有最高優先級(有點類似于Servlet“啟動時加載”值 ) )。
package com.marco.springchain;
import java.util.Collections;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.stereotype.Component;
@Component
public class PrinterChain {@Autowiredprivate List<Printer> printers;@PostConstructpublic void init() {Collections.sort(printers, AnnotationAwareOrderComparator.INSTANCE);}public void introduceUser(User user) {for (Printer printer : printers) {printer.print(user);}}
}
src / main / resources中的spring-config.xml。
<?xml version='1.0' encoding='UTF-8'?>
<beans xmlns='http://www.springframework.org/schema/beans'xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'xmlns:aop='http://www.springframework.org/schema/aop'xmlns:tx='http://www.springframework.org/schema/tx'xmlns:context='http://www.springframework.org/schema/context'xmlns:util='http://www.springframework.org/schema/util'xsi:schemaLocation='http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd' default-lazy-init='true'><context:component-scan base-package='com.marco.springchain'/>
</beans>
最后,一個主類來測試我們的鏈。
package com.marco.springchain;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainTest {public static void main(String[] args) {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext('spring-config.xml');PrinterChain printerChain = (PrinterChain) context.getBean('printerChain');printerChain.introduceUser(new User('Marco Castigliego', 'M'));printerChain.introduceUser(new User('Julie Marot', 'F'));}
}
輸出:
Hello Mr Marco Castigliego
Welcome to the autowired chain Mr Marco Castigliego
Goodbye Mr Marco Castigliego
Cleaning space after Mr Marco Castigliego
Cleaning memory after Mr Marco Castigliego
Hello Mrs Julie Marot
Welcome to the autowired chain Mrs Julie Marot
Goodbye Mrs Julie Marot
Cleaning space after Mrs Julie Marot
Cleaning memory after Mrs Julie Marot
希望您喜歡這個例子。
參考: 使用來自我們的JCG合作伙伴 Marco Castigliego的Spring @Autowired List的責任鏈,位于“ 刪除重復和修復不良名稱”博客中。
翻譯自: https://www.javacodegeeks.com/2012/11/chain-of-responsibility-using-spring-autowired-list.html