Spring入门学习 (三) Spring AOP 详解

By | 2014/08/26

Spring AOP 详解

首先介绍一下aop的有关概念。关于aop的相关概念,帮助文档给了我们详细的说明,但是个人感觉,文档中的说明太过高深,不适合我等技术小白学习。本人根据自己的学习给出自己的理解,不恰当的地方还请大神指点。

直接给出例子

首先,一个实体对象Person


<strong>public</strong><strong>class</strong> Person {

<strong>private</strong> String id;

<strong>private</strong> String name;

<strong>public</strong> Person() {

}

<strong>public</strong> Person(String id, String name) {

<strong>super</strong>();

<strong>this</strong>.id = id;

<strong>this</strong>.name = name;

}

<strong>public</strong> String getId() {

<strong>return </strong>id;

}

<strong>public</strong><strong>void</strong> setId(String id) {

<strong>this</strong>.id = id;

}

<strong>public</strong> String getName() {

<strong>return  </strong>name;

}

<strong>public</strong><strong>void</strong> setName(String name) {

<strong>this</strong>.name = name;

}

}

定义PersonDaoImpl模拟实现数据库操作的类


<strong>public</strong><strong>class</strong> PersonDaoImpl {

&nbsp;

<strong>public</strong><strong>void</strong> add() {

System.<em>out</em>.println("add person");

}

&nbsp;

<strong>public</strong><strong>void</strong> update() {

System.<em>out</em>.println("update person");

}

<strong>public</strong><strong>void</strong> delete() {

System.<em>out</em>.println("delete person");

}

<strong>public</strong> List listAll() {

Person p1 = <strong>new</strong> Person("1001", "person1");

Person p2 = <strong>new</strong> Person("1002", "person2");

List<Person> list = <strong>new</strong> ArrayList<Person>();

list.add(p1);

list.add(p2);

<strong>return</strong> list;

}

<strong>public</strong> Person find() {

Person p1 = <strong>new</strong> Person("1001", "person1");

<strong>      return</strong> p1;

}

}

定义Transaction类,模拟数据库操作中的事务管理


<strong>public</strong><strong>class</strong> Transaction {

<strong>public</strong><strong>void</strong> beginTransaction() {

System.<em>out</em>.println("beginTransaction");

}

/**对应后置通知

* @param joinPoint

*     通过joinPoint可以得到目标类和目标方法的一些信息

* @param val

*     目标方法的返回值

*     和<aop:after-returning returning="val"/>中returning的值保质一致

*/

<strong>public</strong><strong>void</strong> commit(JoinPoint joinPoint, Object val) {

&nbsp;

System.<em>out</em>.println("commit");

List<Person> list = (List<Person>) val;

<strong>for</strong> (Person p : list) {

System.<em>out</em>.println(p.getName());

}

}

&nbsp;

<strong>public</strong><strong>void</strong> finalMethod() {

System.<em>out</em>.println("最终通知");

}

//对应环绕通知

<strong>public</strong><strong>void</strong> arroundMethod(ProceedingJoinPoint joinPoint) {

<strong>try</strong> {

joinPoint.proceed(); // 让目标类的目标方法执行

} <strong>catch</strong> (Throwable e) {

// <strong>TODO</strong> Auto-generated catch block

e.printStackTrace();

}

}

&nbsp;

<strong>public</strong><strong>void</strong> throwMehod(Throwable except) {

System.<em>out</em>.println(except.getMessage());

}

}

最后,给出客户端AopTest测试类


<strong>public</strong><strong>class</strong> AopTest {

@Test

<strong>public</strong><strong>void</strong> test(){

ApplicationContext context = <strong>new</strong> ClassPathXmlApplicationContext("cn/ytu/aop/xml/applicationContext.xml");

PersonDaoImpl dao = (PersonDaoImpl) context.getBean("personDao");

dao.listAll();

}

}

配置文件applicationContext.xml


<?xml version=<em>"1.0"</em> encoding=<em>"UTF-8"</em>?>

<beans xmlns=<em>"http://www.springframework.org/schema/beans"</em>

xmlns:xsi=<em>"http://www.w3.org/2001/XMLSchema-instance"</em>

xmlns:aop=<em>"http://www.springframework.org/schema/aop"</em>

xsi:schemaLocation=<em>"http://www.springframework.org/schema/beans</em>

<em>           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd</em>

<em>           http://www.springframework.org/schema/aop </em>

<em>           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"</em>>

<!--

1、目标类

2、切面

3、进行aop的配置

-->

<!-- 目标类 -->

<bean id=<em>"personDao"</em> class=<em>"cn.ytu.aop.xml.PersonDaoImpl"</em>></bean>

<!-- 切面声明 -->

<bean id=<em>"transaction"</em> class=<em>"cn.ytu.aop.xml.Transaction"</em>></bean>

<!-- aop配置 -->

<aop:config>

<!-- 配置切入点 execution(* cn.itcast.spring0401.aop.xml.PersonDaoImpl.*(..))-->

<aop:pointcut expression=<em>"execution(* cn.ytu.aop.xml.PersonDaoImpl.*(..))"</em> id=<em>"perform"</em>/>

<!-- 配置切面 -->

<aop:aspect ref=<em>"transaction"</em>>

<!-- 前置通知 -->

<aop:before method=<em>"beginTransaction"</em> pointcut-ref=<em>"perform"</em>/>

<!-- 后置通知 -->

<aop:after-returning method=<em>"commit"</em> pointcut-ref=<em>"perform"</em> returning=<em>"val"</em>/>

<!-- 最终通知 -->

<aop:after pointcut-ref=<em>"perform"</em> method=<em>"finalMethod"</em> />

<!-- 环绕通知 -->

<aop:around method=<em>"arroundMethod"</em> pointcut-ref=<em>"perform"</em> />

<!-- 异常通知 -->

<aop:after-throwing method=<em>"throwMehod"</em> pointcut-ref=<em>"perform"</em> throwing=<em>"except"</em>/>

</aop:aspect>

</aop:config>

</beans>

首先,通过这个例子来说明aop中相关概念

(1).切面(Aspect:在本例中“切面”就是Transaction类的行为。

(2).连接点(Joinpoint):程序执行过程中的某一行为,具体说就是在客户端调用的目标对象或者代理对象中的方法。对应本例中的dao.listAll();

(3).通知(Advice):简单说,通知就是切面中的方法.对应本例中的Transaction类中的一系列方法。

(4).切入点(Pointcut):定义“事件”发生的条件。

(5).目标对象(Target Object) :被一个或者多个切面所通知的对象。对应本例中的PersonDaoImpl

下面,详细介绍如何通过xml配置aop

  1. 首先导入aop相关的jar文件

Aspectjweaver.jar与aspectjrt.jar

  1. 加入与aop相关的xsd

xmlns:aop=”http://www.springframework.org/schema/aop”

http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd

  1. 引入目标类,切面

<!– 目标类 –>

<bean id=“personDao” class=“cn.ytu.aop.xml.PersonDaoImpl”></bean>

<!– 切面声明 –>

<bean id=“transaction” class=“cn.ytu.aop.xml.Transaction”></bean>

 

  1. 进行aop的配置

<aop:config>

<!–

配置aop的切入点

id 是切入点的标识

expression 为切入点的表达式

切入点的表达式的模板

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)

参数详解

modifiers-pattern 修饰符可选 public private protected

ret-type-pattern 返回类型必选 * 代表任意类型

declaring-type-pattern 方法的声明类型可选

name-patterm 方法名称类型   必选

set* 以set开头的所有的方法名称

param-pattern 参数匹配   必选

(..) 任意多个参数,每个参数任意多个类型

(*,String) 两个参数第一个是任意类型,第二个是String

throws-pattern 异常的匹配模式可选

<aop:pointcut expression=”execution(* cn.ytu.aop.xml.PersonDaoImpl.*(..))” id=”perform”/>

<!–

配置切面

ref 指向声明切面的类

–>

<aop:aspect ref=”transaction”>

<!–

前置通知

pointcut-ref 引用一个切入点

–>

<aop:before method=”beginTransaction” pointcut-ref=”perform”/>

<!–

后置通知

returning 目标方法的返回值

如果目标方法中有可能存在异常,异常确实发生了,这个时候,后置通知将不再执行

–>

<aop:after-returning method=”commit” pointcut-ref=”perform” returning=”val”/>

<!–

最终通知

不能得到目标方法的返回值

无论目标方法是否有异常,最终通知都将执行

资源的关闭、连接的释放写在最终通知里

–>

<aop:after pointcut-ref=”perform” method=”finalMethod”/>

<!–

环绕通知

ProceedingJoinPoint的proceed方法就是目标对象的目标方法

环绕通知可以控制目标对象目标方法执行

–>

<!–

<aop:around method=”aroundMethod” pointcut-ref=”perform”/>

–>

<!–

异常通知

在异常通知中获取目标方法抛出的异常

–>

<aop:after-throwing method=”throwingMethod” pointcut-ref=”perform” throwing=”except”/>

</aop:aspect>

</aop:config>

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.