弹簧可配置魔术
Spring框架有幾個提供一系列服務的模塊,其中許多模塊僅可用于托管對象(Spring Bean)。有關這些服務的一些示例是依賴注入,事務管理,AOP服務等。當我們使用時,一切都很好對象即服務,因此由Spring在特定范圍內進行管理。 但是有時候我們需要我們的領域對象擁有這些服務。 通常,域對象是使用new關鍵字創建的,因此默認情況下無法使用spring對其進行管理。
在我的上一篇文章( 如何在Spring 3.x中使用事件 )中,我們有一個名稱為Order的域對象。 對于對象之間的解耦,我們使用了事件。 但是,只有受管bean才能在Spring框架中引發事件(可能是您知道并具有此功能的每個框架)。
Spring引入了一個名為Configurable的注釋。 在我們的域對象上使用此注釋使它們由spring管理。
但是它是如何工作的:出于其目的可配置,需要AspectJ Compiler,您的類需要在編譯時或加載時提高字節碼,直到可以滿足您的要求。
我想帶給您一個有關如何在應用程序中配置和使用可配置電源的簡單示例。 最好讓環境對象使所有系統都可以訪問其屬性以捕獲有關系統的信息。 例如,我們需要知道系統的當前時間,簡單的解決方案是使用Calendar.getInstance().getTime()或new Date()
但是有一些缺陷,您的代碼對于需要測試日期斷言的部分將無法進行測試(我將盡快編寫一系列后測試和可測試代碼)。
另一個問題是當您希望系統使用偽時鐘時。 例如,您的客戶希望在假期(最后一個非假期日期)使用系統。
因此,為這些需求提供一種機制很有價值。 作為此示例中的一個簡單解決方案,我將創建一個環境接口,該接口具有一個方法(getCurrentTime())。 如果我需要系統時間,則代碼中的每個地方都將使用此方法。 在我可以愉快地使用此方法之前,必須將環境接口注入到我的對象中。 Spring bean對使用Environment沒有任何問題,但是在我們的域對象中,我們必須使用Configurable Annotation。
如果使用Maven,則需要將以下依賴項添加到pom中:
<groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>3.1.1.RELEASE</version><dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.6.8</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.8</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjtools</artifactId> <version>1.6.8</version> </dependency>要使用maven編譯應用程序,可以使用以下Aspectj-maven-plugin配置:
<build><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>aspectj-maven-plugin</artifactId><version>1.4</version><configuration><showWeaveInfo>true</showWeaveInfo><source>1.6</source><target>1.6</target><Xlint>ignore</Xlint><complianceLevel>1.6</complianceLevel><encoding>UTF-8</encoding><verbose>false</verbose><aspectLibraries><aspectLibrary><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId></aspectLibrary></aspectLibraries></configuration><executions><execution><goals><goal>compile</goal><goal>test-compile</goal></goals></execution></executions><dependencies><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.6.8</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjtools</artifactId><version>1.6.11</version></dependency></dependencies></plugin></plugins></build>如果使用IDE編譯代碼,請不要忘記將其編譯器更改為AspectJ。 您可以在AspectJrt目錄中的本地Maven存儲庫中找到它。
假設有一個Product類,我們想知道其創建日期以及銷售日期。
@Configurable(preConstruction = true)public class Product {private final String name;private final String description;private final Date createDate;private Status status;private Date saleDate;@Autowiredprivate Environment environment;public Product(String name, String description) {this.name = name;this.description = description;this.status = Status.PENDING;this.createDate = environment.getCurrentDate();}public void sell() {this.status = Status.SALE;this.saleDate = environment.getCurrentDate();}public Date getCreateDate() {return createDate;}public Date getSaleDate() {return saleDate;}public static enum Status {PENDING, SALE;}}產品是一個非常簡單的類,我們使用preConstruction = true是因為我們的產品構造需要使用環境。
環境及其實現也非常簡單:
public interface Environment {Date getCurrentDate();}public class DefaultEnvironment implements Environment {@Overridepublic Date getCurrentDate() {return new Date();}}public class MockEnvironment implements Environment {private Date date;@Overridepublic Date getCurrentDate() {return this.date;}public void setCurrentDate(Date date){this.date = date;}}MockEnvironment是在測試包中創建的,因為我們僅在測試中需要此類。 除了使用此類之外,您還可以使用一些模擬庫作為Mocktio及其擴展(Springockito)。 但是在此示例中,我們的重點不在它們上。
我們的測試也非常簡單:
@ContextConfiguration({"classpath*:context.xml","classpath*:test-context.xml"})public class ProductTest extends AbstractJUnit4SpringContextTests {final Date time = Calendar.getInstance().getTime();@AutowiredEnvironment environment;@Beforepublic void before() {((MockEnvironment) this.environment).setCurrentDate(time);}@Testpublic void created_product_should_have_current_environment_date() {final Product product = new Product("", "");Assert.assertEquals(time, product.getCreateDate());}@Testpublic void sell_should_set_createDate_to_now(){final Product product = new Product("", "");product.sell();Assert.assertEquals(time, product.getSaleDate());}} 您可以從以下網址下載源代碼: https : //github.com/psycho-ir/Spring-Configurable.git
翻譯自: https://www.javacodegeeks.com/2013/09/spring-configurable-magic.html
總結
- 上一篇: 安卓4升级到安卓5.0(安卓4升级)
- 下一篇: 替代JavaOne 2013