使用Spring AOP實現活動記錄模式

在班級設計中,我們應就每個班級的職責分配做出決定。 如果我們選擇的不錯,系統將更易于理解,維護和擴展。

幾乎我們所有的項目都有一個持久層,即關系數據庫,文檔存儲或僅XML文件。 通常,您將使用DAO模式在業務對象和數據存儲之間實現抽象接口。

在這篇文章中,但我將解釋另一種可以代替DAO模式使用的模式。 活動記錄模式是一種體系結構模式,它迫使您對模型類實施CRUD操作,因此模型類本身負責保存,刪除和從數據庫加載。

要實現此模式,有許多策略可以遵循,但是對我而言,最好的方法是使用面向方面的編程 ,因為我們仍然保持關注點分離,有利于隔離的單元測試,而不破壞封裝。

面向方面的編程需要將程序邏輯分解為不同的部分。 這些部分被稱為橫切關注點,因為它們“ 跨越 ”程序中的多個抽象。 橫切關注點的示例可以是日志記錄,事務管理器錯誤管理器拆分大型數據集 。 對于在這里沒有太多秘密的方面的人們來說,要使用它們,您只需創建一個定義建議和切入點的方面,然后就可以執行您的方面了。

我想我們大多數人都使用了上一段中所述的面向方面的編程,但是使用ITD(類型間聲明)功能的人會更少。

類型間聲明提供了一種表達橫切關注點的方法,這些關注點影響了模塊的結構,從而使程序員可以聲明另一個類的成員。

正如我們在我的國家說“ 不好說,但很好理解 “,ITD是從一個方面宣布新的組件屬性,方法,注解 )的方式。

AspectJ是Java 的面向方面的擴展。 AspectJ支持ITD ,因此在本文中將使用它。 此外,我建議您安裝AJDT插件,因為它將幫助您開發方面,并快速概述了哪些Java類已被方面化。

如果您不了解什么是ITD ,請不用擔心,這是一個典型的概念示例,最好通過示例來理解。

讓我們從一個簡單的例子開始:

想象一下必須為汽車建模。 您將擁有一個帶有某些屬性的汽車類,在此示例中,三個屬性( vin號,行駛里程model )就足夠了。

public class Car {public void setVin(String vin) {this.vin = vin;}public String getVin() {return this.vin;}private String vin;public void setMileNum(int mileNum) { this.mileNum = mileNum;}public int getMileNum() {return this.mileNum;}private int mileNum;public void setModel(String model) {this.model = model;}public String getModel() {return this.model;}private String model; }

這是一個具有三個屬性以及它們的gettersetterPOJO

現在我們要添加持久層,但是在這種情況下,我們將POJO持久化為 XML文件而不是數據庫。 因此,應將Car對象轉換為XML流。 為此,將使用JAXB批注。 對于那些不知道的人, JAXB允許開發人員將Java類映射到XML表示,反之亦然。

我確信,想到的第一個想法是使用@XmlRootElement注釋Car類(在JAXB中映射根元素的注釋)。 不要那樣做,使用方面 。 您的第一個任務是嘗試維護Car文件盡可能簡單。 要使用ITD添加注釋,很簡單:

public aspect Car_Jaxb {declare @type: Car: @XmlRootElement;
}

使用@type可以公開注釋哪個成員。 在這種情況下,只能上課。 其他方法是@method@constructor@field 。 然后元素模式應該被注釋,在這種情況下是Car類,但是您可以使用任何正則表達式,例如o rg.alexsotob .. *。 最后是注釋

下一步是使用JAXB類來編組/解組對象。 在此示例中,我使用spring-oxm軟件包,簡要地您將了解原因。 Spring-oxmspring-core的一部分,其中包含用于處理O / X Mapping的類

這個spring模塊為每個受支持的Xml綁定包含一個類。 在我們的情況下, Jaxb2Marshaller用作編組器和解組器。

您可能正在考慮創建一個服務類,在其中注入Jaxb2Marshaller實例。 該服務將包括兩個方法(保存和加載),以Car類作為參數或返回值。 抱歉,這樣做是要實現DAO模式。 讓我們實現Active Record模式方法。 正如您可能會想到的, aspectj可以幫助您避免將概念混入同一源文件中。

讓我們更新以前的方面文件,以便JAXB所需的所有邏輯都在同一文件中。

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;public aspect Car_Jaxb {declare @type: Car: @XmlRootElement;@Autowiredtransient Jaxb2Marshaller Car.marshaller;public void Car.save(OutputStream outputStream) throws IOException {this.marshaller.marshal(this, new StreamResult(outputStream));}public Car Car.load(InputStream inputStream) throws IOException {return (Car)this.marshaller.unmarshal(new StreamSource(inputStream));}}

看到除了注釋Car類,我們還創建了兩個方法和一個帶注釋的屬性。 屬性必須遵循與方法,< 類名 >點(。)和< 屬性名 >相同的規則。 請注意,在這種情況下,屬性是瞬態的,因為不應綁定到XML文件中。

最后一步是在spring上下文文件中配置marshaller

<?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:oxm="http://www.springframework.org/schema/oxm"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsdhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"><oxm:jaxb2-marshaller id="marshaller"><oxm:class-to-be-bound name="org.alexsotob.itd.Car"/></oxm:jaxb2-marshaller></beans>

沒有太多秘密。 現在讓我們編寫一個單元測試代碼。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="/context.xml")
public class CarOxmBehaviour {@Testpublic void shouldSaveCarToXml() throws Exception {//GivenCar car = new Car();car.setMileNum(1000);car.setModel("Ferrari");car.setVin("1M8GDM9AXKP042788"); //From http://en.wikipedia.org/wiki/Vehicle_Identification_Number//WhenByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();car.save(byteArrayOutputStream);//ThenString expectedMessage = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><car><mileNum>1000</mileNum><model>Ferrari</model><vin>1M8GDM9AXKP042788</vin></car>";String xmlMessage = byteArrayOutputStream.toString("UTF-8");assertThat(the(xmlMessage), isEquivalentTo(the(expectedMessage)));  }}

用令人驚訝的NullPointerException運行紅色的junit類和BOOMMarshaller是在Spring上下文中創建的,但是沒有注入到Car類中(Car不是由spring 容器管理的,因此無法注入)。 現在,我想您是在告訴自己:“ 我告訴您,服務層會更好,因為它將由Spring進行管理,并且自動裝配功能會完美工作 。” 但是,拭目以待。 如何使用spring-aspects模塊? Spring Aspects包含一個注釋驅動的方面( @Configurable ),允許任何對象的依賴項注入,無論是否受容器控制。 因此,讓我們應用最后兩個更改,應用程序將運行。

首先是創建一個新的aspectj文件,以將Car類注釋為Configurable

import org.springframework.beans.factory.annotation.Configurable;public aspect Car_Configurable {declare @type: Car: @Configurable;}

最后修改spring上下文文件以允許@Configurable注釋。

<?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:oxm="http://www.springframework.org/schema/oxm"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsdhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"><oxm:jaxb2-marshaller id="marshaller"><oxm:class-to-be-bound name="org.alexsotob.itd.Car"/></oxm:jaxb2-marshaller><context:spring-configured></context:spring-configured>
</beans>

添加< context:spring-configured > </ context:spring-configured >命名空間就足夠了。 結果,任何時候您實例化一個對象(通過“ new ”關鍵字)時,Spring都會嘗試對該對象執行依賴注入。

現在再次運行單元測試,綠色將侵入您的計算機:D。

ITD是一個很好的解決方案,可以自己負責設計類。 它為您提供了編寫可維護且易于理解的代碼的機會,而不會丟失封裝。 當然,您應該注意不要在各方面的類中具有較高的耦合,而應將它們轉換為“上帝類”。

注意,實現相同的方法但是使用關系數據庫,就像將Jaxb2Marshaller更改為EntityManager一樣簡單。

我希望您發現這篇文章有用。

下載完整代碼

參考:來自JCG合作伙伴的 Spring AOP實現活動記錄模式 ? 在一個罐子統治他們所有博客的亞歷克斯·索托。


翻譯自: https://www.javacodegeeks.com/2012/02/implementing-active-record-pattern-with.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/373723.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/373723.shtml
英文地址,請注明出處:http://en.pswp.cn/news/373723.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java基礎之反射

框架都要用到反射技術&#xff0c;反射都要用到一個類Class. java程序中的各個java類屬于同一類事物&#xff0c;描述這類事物的java類名就是Class. 得到字節碼的方式有三種&#xff1a; Date.class;new Date().getClass();Class.forName("java.lang.String");最后一…

php socketconnect連接失敗_PHP設計模式之模板方法模式

模板方法模式&#xff0c;也是我們經常會在不經意間有會用到的模式之一。這個模式是對繼承的最好詮釋。當子類中有重復的動作時&#xff0c;將他們提取出來&#xff0c;放在父類中進行統一的處理&#xff0c;這就是模板方法模式的最簡單通俗的解釋。就像我們平時做項目&#xf…

linux系統硬件配置查看方法

一&#xff1a;查看cpu more /proc/cpuinfo | grep "model name" grep "model name" /proc/cpuinfo 如果覺得需要看的更加舒服 grep "model name" /proc/cpuinfo | cut -f2 -d: 二&#xff1a;查看內存 grep MemTotal /proc/meminfo grep MemT…

java String源碼學習

public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence {/**char數組用于字符的存儲 */private final char value[];/** 緩存string的hash碼 */private int hash; // Default to 0public String() {/**無參構造函數,打印值為&quo…

JBoss AS 7.1.0.Final“ Thunder”發布-Java EE 6 Full Profile認證!

在JBoss AS7上進行了大約一年的開發后&#xff0c;我們現已發布7.1.0.Final“ Thunder” &#xff01; 可從此處的通常位置下載該文件。 對于JBoss AS7團隊來說&#xff0c;這是一個非常大的成就&#xff0c;我們為此版本感到非常自豪。 這個版本包含了7.1.0.CR1b的許多錯誤修復…

數據庫建表練習(10.11作業)

轉載于:https://www.cnblogs.com/HRZJ/p/5951897.html

天干地支計算公式_天干地支主怎樣計算?

回答&#xff1a;少女時代級別&#xff1a;碩士研究生2009-01-08 20:34:04來自&#xff1a;貴州省貴陽市我國古代是用天干地支來紀年的&#xff0c;現代社會已很少使用。一來現今社會已經離不開國際化&#xff0c;沿用老的歷法已經不現實&#xff1b;二來天干地支在民間多用于算…

從程序員到CTO的Java技術路線圖

時間:2013-05-29 17:39來源:www.chengxuyuans.com在技術方面無論我們怎么學習&#xff0c;總感覺需要提升自已不知道自己處于什么水平了。但如果有清晰的指示圖供參考還是非常不錯的&#xff0c;這樣我們清楚的知道我們大概處于那個階段和水平。 Java程序員 高級特性 反射、泛型…

Linux的網卡相關

檢測linux下網卡是否正常 1.dmesg | grep eth 如果出現以下 eth0: link up 說明是網卡正常的 eth0: registered as PCnet/PCI II 79C970Aeth0: link upeth0: no IPv6 routers present 2.如果所用網卡是pcI總線的 。用命令&#xff1a;lspci 能看到網卡是存在的。 3.用ethtool…

設置Spring 3開發環境

本教程簡要說明了如何設置典型的環境來開發基于Spring的應用程序。 除了可以正常工作的Windows XP客戶端具有足夠的CPU能力和內存外&#xff0c;本教程沒有其他先決條件。 在教程中&#xff0c;我們將需要安裝以下組件&#xff1a; Java 6 JDK更新26 用于Java EE開發人員的Ecl…

3. 跟蹤標記 (Trace Flag) 1204, 1222 抓取死鎖信息

跟蹤標記&#xff1a;1204/1222 功能及用途&#xff1a; 捕獲SQL Server死鎖信息&#xff0c;并自動存放到錯誤日志(ERRORLOG)中。 舉例&#xff1a; USE tempdb GO CREATE TABLE t1(id int) INSERT t1 SELECT 1CREATE TABLE t2(id int) INSERT t2 SELECT 1 GO --開啟1204/1222…

postgresql建表帶注釋_postgresql建表帶自增id和注釋語句

work是表名&#xff0c;nextval(work_myid_seq::regclass)這個是自增id的設置CREATE TABLE "public"."work" ("id" int8 NOT NULL DEFAULT nextval(work_myid_seq::regclass),"wid" int8,"address" varchar(100) COLLATE &q…

js中window.onload 與 jquery中$(document.ready()) 測試

js中window.onload 與 jquery中$(document.ready())區別&#xff0c;驗證代碼如下(調換js代碼和Jquer代碼書寫順序測試&#xff0c;運行結果一樣&#xff0c;因此與代碼書寫位置沒關系)&#xff1a;<html> <head> <script typetext/javascript srcjquery-1.11.1…

5. Longest Palindromic Substring

更新&#xff1a; 之前那種dp太笨重了有個非常的輕巧的做法&#xff0c;原理都是一樣的。 轉移方程不變&#xff0c;但是不需要特別的初始化 判斷某個格子是不是true&#xff0c;是 1.要么長度小于3&#xff0c;要么dp[start1][end-1]true 2.并且s.charAt(start) s.charAt(end…

Java中的定制國際化(i18n)

國際化&#xff08;i18n&#xff09;在我們的軟件項目中非常重要。 它主要帶來以下好處&#xff1a; 將UI字符串外部化為除代碼文件之外的外部文件&#xff0c;以及易于管理的UI內容。 支持多種語言。 在這篇文章中&#xff0c;將為Eclipse和Java項目提供一個簡短的i18n實際示…

SEO 百度后臺主動推送鏈接

實踐步驟&#xff0c;先用爬蟲程序將本網站的所有連接爬取出來&#xff0c;再用python文件處理程序把爬蟲來的東東整理成一行一個鏈接的文本格式。再用postman接口測試工具&#xff0c;使用post方式&#xff0c;將所有的鏈接post過去&#xff0c;這樣主動推送是最為快速的提交方…

linux版本 如何查kali_000_Kali Linux版本查看和apt源配置

1.查看系統版本# cat /etc/issue# lsb_release -a2.查看內核信息# uname -a3.更新源# cp /etc/apt/source.list{,.bak}# vim /etc/apt/sources.list//備注&#xff1a;國外源速度太慢&#xff0c;這里禁止&#xff1b;網絡中的部分源已經過期&#xff0c;建議更換其它源。# kal…

nyoj--127--星際之門(一)(生成樹的數量)

星際之門&#xff08;一&#xff09; 時間限制&#xff1a;3000 ms | 內存限制&#xff1a;65535 KB難度&#xff1a;3描述公元3000年&#xff0c;子虛帝國統領著N個星系&#xff0c;原先它們是靠近光束飛船來進行旅行的&#xff0c;近來&#xff0c;X博士發明了星際之門&…

Oracle 常用的一些函數

字符函數 SELECT UPPER(hello WORLD) FROM DUAL; //將小寫字母變為大寫字母SELECT LOWER(hello WORLD) FROM DUAL; //將大寫字母變為小心字母SELECT INITCAP(hello WORLD) FROM DUAL; //將字符串的首字母大寫SELECT CONCAT(hello, world) FROM DUAL; //字符串拼…

Apache Camel 2.9發布–十大變化

在2011年的最后一天&#xff0c;阿帕奇駱駝制品被成功地推到了中央行銷倉庫&#xff0c;距離香檳酒瓶破裂并進入2012年僅1.5個小時之遙。 2.9版是創紀錄的發行版&#xff0c;自5個月前發布2.8版以來&#xff0c;已解決了約500張JIRA票證。 以下是10個最明顯的改進和新功能的分…