使用Spring AOP实现活动记录模式
几乎我们所有的项目都有一个持久层,即关系数据库,文档存储或仅XML文件。 通常,您将使用DAO模式在业务对象和数据存储之间实现抽象接口。
在这篇文章中,但我将解释另一种可以代替DAO模式使用的模式。 活动记录模式是一种体系结构模式,它迫使您对模型类实施CRUD操作,因此模型类本身负责保存,删除和从数据库加载。
要实现此模式,有许多策略可以遵循,但是对我而言,最好的方法是使用面向方面的编程 ,因为我们仍然保持关注点分离,有利于隔离的单元测试,而不破坏封装。
面向方面的编程需要将程序逻辑分解为不同的部分。 这些部分被称为横切关注点,因为它们“ 跨越 ”程序中的多个抽象。 横切关注点的示例可以是日志记录,事务管理器 , 错误管理器或拆分大型数据集 。 对于在这里没有太多秘密的方面的人们来说,要使用它们,您只需创建一个定义建议和切入点的方面,然后就可以执行您的方面了。
我想我们大多数人都使用了上一段中所述的面向方面的编程,但是使用ITD(类型间声明)功能的人会更少。
类型间声明提供了一种表达横切关注点的方法,这些关注点影响了模块的结构,从而使程序员可以声明另一个类的成员。
正如我们在我的国家说“ 不好说,但很好理解 “,ITD是从一个方面宣布新的组件类 ( 属性,方法,注解 )的方式。
AspectJ是Java 的面向方面的扩展。 AspectJ支持ITD ,因此在本文中将使用它。 此外,我建议您安装AJDT插件,因为它将帮助您开发方面,并快速概述了哪些Java类已被方面化。
![](https://2.bp.blogspot.com/-d620eEJEaUo/T0EHoYZ7rqI/AAAAAAAAAYQ/Bqij_6qa8eU/s1600/logo.gif)
如果您不了解什么是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; }
这是一个具有三个属性以及它们的getter和setter的POJO 。
现在我们要添加持久层,但是在这种情况下,我们将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-oxm是spring-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类和BOOM 。 Marshaller是在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
使用Spring AOP实现活动记录模式相关推荐
- spring aop实践_使用Spring AOP实现活动记录模式
spring aop实践 在课堂设计过程中,我们应就每个班级的职责分配做出决定. 如果我们选择的不错,系统将更易于理解,维护和扩展. 我们几乎所有的项目都有一个持久层,即关系数据库,文档存储或仅XML ...
- spring aop示例_Spring Profile模式示例
spring aop示例 最近,我们介绍了Spring Profiles的概念. 此概念是针对不同部署环境的轻松配置区分符. 直接的用例(已提出)是对相关的类进行注释,以便Spring根据活动的配置文 ...
- 什么是活动记录模式?
活动记录是指封装了数据库表或视图的一行的对象,对象可以包含数据和行为. 活动记录对象的结构应尽可能的接近于相关联的数据表结构. 活动对象中通常会包含用来执行查找的查找方法.CURD操作.验证以及领域相 ...
- Spring AOP的日志记录
现在的项目是Spring+MyBatis,前段时间项目经理让我干了一个活,就是给所有的controller里的所有方法加上日志记录的代码,其实没有多少,也就300来个方法,也没有抱怨什么,一边打着瞌睡 ...
- Spring AOP 自定义注解记录操作日志
1.自定义注释 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface ...
- Spring AOP进行日志记录,管理
http://blog.csdn.net/sd0902/article/details/8393770 转载于:https://my.oschina.net/liangzhenghui/blog/84 ...
- Spring AOP概述及底层实现原理
Spring AOP概述及底层实现原理 aop概述 AOP全称为Aspect Oriented Programming的缩写,意为:面向切面编程.将程序中公用代码进行抽离,通过动态代理实现程序功能的统 ...
- 使用Spring AOP进行面向方面的编程
面向方面的编程(AOP)是指将辅助功能或支持功能与主程序的业务逻辑隔离开来的编程范例. AOP是用于分离横切关注点的有前途的技术,这在面向对象的编程中通常很难做到. 以此方式增加了应用程序的模块化,并 ...
- Spring AOP 从入门到放弃
Spring AOP 主要内容 代理模式 代理模式在 Java 开发中是一种比较常见的设计模式.设计目的旨在为服务类与客户类之间插入其他功能,插入的功能对于调用者是透明的,起到伪装控制的作用.如租房的 ...
最新文章
- 卸载sharepoint2013
- 关闭 启动_Steam如何关闭开机自动启动
- java存入数据库是问号_Java插入中文到数据库中文变成问号解决
- 详解@Autowired、@Qualifier和@Required
- 使用WTMPlus快速搭建发卡网
- 移植驱动完毕后加载时的version magic报错原因以及解决办法
- TensorFlow版本的HelloWord
- 原生vue.js实现待办事项清单,支持增删改查
- 2017年度工作总结
- 关于@JsonView的使用心得及一些隐蔽的注意事项
- vosviewer保存成PDF文件时没有文字
- 认知无线电matlab代码详解,Cognitive-Radio--Matlab-code 认知无线电, 通信, 仿真代码 238万源代码下载- www.pudn.com...
- ch2_8_2求解幸运数问题
- C语言的 a, *a, a
- easyconnect 通过Vmware虚拟机挂ccproxy变非全局代理
- 出自上帝之手的精妙算法 - Algorithm from THE BOOK (1)
- 计算机电源故障维修方法,电脑辅助电源故障的维修方法
- npx mrm lint-staged 报 Preset “default” not found. 解决方案
- 腾讯安全天御获“零售风向标”《2020中国零售品牌数字化转型白皮书》推荐
- oracle判断字符串以什么开头_oracle 如何查找特定字母开头的某个字段?
热门文章
- 矩阵累积相乘 java_累积:轻松自定义Java收集器
- ide 日志 乱码_IDE日志分析方法pt。 2
- java ee的小程序_用微服务和容器替换旧版Java EE应用程序服务器
- tdd java_Java TDD简介–第2部分
- u3d ab包 循环依赖_为什么要保持软件包依赖项自由循环的五个原因
- 卡夫卡队列_卡夫卡编年史队列基准
- 从Java 11中删除的API
- hibernate关联映射_具有关联映射的Hibernate Composite ID
- java线程死锁_Java线程死锁–案例研究
- JAX-RS和JSON-P集成