當前位置:
首頁 > 知識 > Spring 和 AspectJ實現DDD領域驅動設計

Spring 和 AspectJ實現DDD領域驅動設計

DDD能夠幫助我們跟隨業務概念的複雜變化而順利實現軟體開發。無論是Spring或EJB3,下面三層架構:

  • 領域對象

    , 映射到關係資料庫的POJO. .
  • 數據訪問層

    – 典型的無態服務, 包裝(JDBC, Hibernate, JPA, iBatis)等實現於內部,對外提供抽象,比如DAO模式
  • 業務服務層

    – 另外一種無態服務, 對領域對象進行操作. 一般的設計是引入了一系列領域對象,或返回域對象,執行這些對象的邏輯,然後通過數據訪問層訪問資料庫。服務層是偉大的,因為它專註於業務邏輯,委派技術細節DAO層。
  • 用戶界面

    – 面向Web留nowadays, typically via web browser. User interface is great because… just the fact it is.

一個領域模型對象內部封裝了狀態,對象的操作是一種有態方式, 對象在行為被調用後導致內部狀態變化,對象的狀態切換是由行為影響導致,這是一種狀態模式。

以Reservation 預約實體為例子,它有下面幾個狀態:

Spring 和 AspectJ實現DDD領域驅動設計

打開今日頭條,查看更多圖片

當Reservation預訂時被創建,它有新的狀態(狀態)。一些授權人可以接受預訂,比如暫時保留他們的座位,並發送一封電子郵件,要求他為預訂支付鈔票。然後,當用戶執行貨幣轉移,錢入賬,列印票和第二電子郵件發送到客戶端。

首先Reservation實體是有方法行為的,不是以前的貧血模型,只有屬性的setter/getter方法,這些行為用來切換狀態變化的。

如果我們使用Hibernate持久化Reservation,帶來問題是,Spring如何知道Hibernate管理的那個Reservation實體對象,當Hibernate創建領域對象時,SPring並不知道那個實例,也就無法接管這個領域對象,服務就無法操作到那個Reservation實體。

首先我們使用@Configurable配置領域對象:

@Configurable

@Entity

public class Reservation implements Serializable {

//...

}

這是告訴Spring要管理Reservation對象,而@Entity屬於Hibernate標註,Spring不知道Hibernate何時創建它,這時必須使用AspectJ。配置中加入:

<context:load-time-weaver/>

告訴Spring使用 AspectJ load-time weaving (LTW). 對Hibernate載入的對象進行織入管理。

但是會出現下面錯誤:

java.lang.IllegalStateException: ClassLoader [org.apache.catalina.loader.WebappClassLoader] does NOT provide an "addTransformer(ClassFileTransformer)" method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring"s agent: -javaagent:spring-agent.jar

at org.springframework.context.weaving.DefaultContextLoadTimeWeaver.

setBeanClassLoader(DefaultContextLoadTimeWeaver.java:82)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.

initializeBean(AbstractAutowireCapableBeanFactory.java:1322)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.

doCreateBean(AbstractAutowireCapableBeanFactory.java:473)

… 59 more

失敗了,當應用啟動時,其實它並沒有發現AspectJ agent,然後就告訴我們錯誤,加入 -javaagent:spring-agent.jar 到JVM命令參數,Reservation第一次被載入時,agent會發現@Configurable配置,然後將ApectJ的方面aspect應用於它。

用AspectJ將依賴注入到領域對象

配置:

<context:spring-configured />

<context:component-scan base-package="some.package.domain" />

<context:load-time-weaver aspectj-weaving="on" />

使用Hhibernate的實體類代碼:

package come.package.domain;

import java.io.Serializable;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Configurable;

@Configurable

public abstract class Entity<T, ID extends Serializable> {

@Autowired

private SessionFactory sessionFactory;

public T getById(ID id) {

return (T) getSession().get(getClass(), id);

}

public ID save() {

return (ID) getSession().save(this);

}

protected Session getSession() {

return sessionFactory.getCurrentSession();

}

}

編譯時JVM參數加入:

-javaagent:~/.m2/repository/org/springframework/spring-instrument/3.0.2.RELEASE/spring-instrument-3.0.2.RELEASE.jar

詳細配置見Spring 3 AOP配置

預訂模型

回到預訂模型, 因為這個增強的Reservation是Spring-aware.它不管是由Hibernate或Struts2創建的,這樣,我們可以將依賴注入到領域對象中:

@Configurable

@Entity

public class Reservation implements Serializable {

@PersistenceContext

private transient EntityManager em;

@Transactional

public void persist() {

em.persist(this);

}

//...

}

注意,我們已經將Spring和Hibernate配置無縫地整合在一個領域模型中了。@Entity和@PersistenceContext是Hibernate,@Configurable和@Transactional是Spring的。

你能注入通常依賴dependencies (其他 Spring beans)到你的領域對象.你可以選擇(@Autowire or even 或者 @Resource ,或者手工setting properties.

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

HashMap和Hashtable的6個區別
Selenium python 實現點擊非select/option下的懸浮隱藏文本

TAG:程序員小新人學習 |