您的位置:首页 > 编程语言 > Java开发

spring2.0基于XML Schema的AOP实现以及AOP事务

2011-06-24 10:56 561 查看
1. Before Advice和After Advice

import org.aspectj.lang.JoinPoint;

public class LogAdvice {

//基于XML Schema实现Before Advice时,Advice类不用实现org.springframework.aop.MethodBeforeAdvice接口(spring2.0才提供)
//before方法是在目标对象上的方法被执行前要执行的方法,before方法中的JoinPoint参数是可选项,可以根据需要决定是否需要JoinPoint参数,
//通过JoinPoint对象可以获得目标对象(getTarget())、目标方法上的参数(getArgs())等信息,然后在XML中为目标对象指定代理
public void before(JoinPoint joinPoint) {
//System.out.println(" method before: " + joinPoint.getTarget().getClass().getName() +"."+ joinPoint.getSignature().getName() + " START");
for(Object o :joinPoint.getArgs()){
if (o == null){
//System.out.println("param : " + o);
} else {
//System.out.println("param : " + o.toString());
}
}
}

//基于XML Sechma实现After Returning Advice时,不需要org.springframework.aop.AfterReturningAdvice接口(spring2.0才提供)
public void after(JoinPoint joinPoint) {
//System.out.println(" method after : " + joinPoint.getTarget().getClass().getName() +"."+ joinPoint.getSignature().getName() + " END");
}
}

2. Around Advice

import org.aspectj.lang.ProceedingJoinPoint;

public class LogAroundAdvice {

//Spring2.0中,Around Advice不用实现org.aoplliance.intercept.MethodInterceptor接口,但Advice方法必须返回对象,并且必须定义一个ProceedingJoinPoint参数
public Object invoke(ProceedingJoinPoint joinPoint) {

System.out.println(" LogAroundAdvice before " + joinPoint.getSignature().getName());
Object retVal = null;
try {
retVal = joinPoint.proceed();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(" LogAroundAdvice after " + joinPoint.getSignature().getName());
return retVal;
}

}

3. Throw Advice

import org.aspectj.lang.JoinPoint;

public class LogThrowingAdvice {

//Spring2.0中,Throw Advice不用实现org.springframework.aop.ThrowsAdvice接口,但Advice方法必须定义Throwable(或其子类)参数
//<aop:after-throwing></aop:after-throwing>中必须定义throwing属性,指定方法中的throwable参数.Spring将根据异常类型决定是否调用afterThrowing方法.
public void afterThrowing (JoinPoint joinPoint, Throwable throwable) {
System.out.println(" LogThrowingAdvice : " + joinPoint.getSignature().getName());
}
}

4.

<!--编写业务逻辑方法
编写业务逻辑方法时,最好将异常一直向上抛出,在表示层(struts)处理
关于事务边界的设置,通常设置到业务层,不要添加到Dao上
-->
<!-- =================================================================== -->
<!-- AOP: Configuration and Aspects -->
<!-- =================================================================== -->
<!-- AOP配置,使用基于XML Sechma声明AOP的方式,需要在XML中加入aop的名称空间 -->
<aop:config>
<!-- 声明事务切入点(配置哪些类的哪些方法参与事务),可以有多个 -->
<aop:pointcut id="managerTx" expression="execution(* *..service.*Manager.*(..))" />
<!-- 通知器(把事务通知绑定到切入点),可以有多个 -->
<aop:advisor pointcut-ref="managerTx" advice-ref="txAdvice" order="0" />
<!--
Spring2.0中,Pointcut的定义包括两个部分:Pointcut表示式(expression)和Pointcut签名(signature).
先看看execution表示式的格式:execution(modifier-pattern?ret-type-pattern?declaring-type-pattern?name-pattern?param-pattern?throws-pattern?)
括号中各个pattern分别表示修饰符匹配(modifier-pattern)、返回值匹配(ret-type-pattern)、类路径匹配(declaring-type-pattern)、方法名匹配(name-pattern)、
参数匹配((param-pattern))、异常类型匹配(throws-pattern),其中后面跟着“?”的是可选项.在各个pattern中可以使用“*”来表示匹配所有.在(param-pattern)中,可以指定具体的参数类型,
多个参数间用“,”隔开,各个也可以用“*”来表示匹配任意类型的参数,如(String)表示匹配一个String参数的方法;(*,String)表示匹配有两个参数的方法,第一个参数可以是任意类型,而第二个参数是String类型;可以用(..)表示零个或多个任意参数.
现在来看看几个例子:
1)execution(* *(..))表示匹配所有方法
2)execution(public * com. savage.service.UserService.*(..))表示匹配com.savage.server.UserService中所有的公有方法
3)execution(* com.savage.server..*.*(..))表示匹配com.savage.server包及其子包下的所有方法
除了execution表示式外,还有within、this、target、args等Pointcut表示式。一个Pointcut定义由Pointcut表示式和Pointcut签名组成,Pointcut定义时,还可以使用and、or、not运算.
-->
<aop:aspect id="logAspect" ref="logAdvice" order="1">
<aop:pointcut id="logPointcut" expression="execution(* *..service.*Manager.*(..)) or execution(* *..dao.*Dao.*(..))"/>
<!-- 前置通知:对于一个通知来说,切入点和对应的通知方法是必须的.也就是说,method属性是必须的,必须给通知指定一个对应方法;pointcut属性和pointcut-ref必须有一个被指定,确定该通知切入点 -->
<aop:before pointcut-ref="logPointcut" method="before"/>
<!-- 后置通知-->
<aop:after pointcut-ref="logPointcut" method="after"/>
</aop:aspect>
<aop:aspect id="logAround" ref="logAroundAdvice" order="2">
<!-- 环绕通知:所有通知中功能最强大的通知-->
<aop:around pointcut="execution(* *..service.*Manager.*(..)) or execution(* *..dao.*Dao.*(..))" method="invoke"/>
</aop:aspect>
<aop:aspect id="logThrowing" ref="logThrowingAdvice" order="3">
<!-- 异常通知:有一个类似于throwing属性来指定该通知匹配的异常类型 -->
<aop:after-throwing throwing="throwable" method="afterThrowing" pointcut="execution(* *..service.*Manager.*(..))"/>
</aop:aspect>
<!-- 返回后通知:用于将链接点的返回值传给通知方法,比aop:after多了个returning属性 -->
</aop:config>

<bean id="logAdvice" class="cn.xue.app.advice.LogAdvice"/>
<bean id="logAroundAdvice" class="cn.xue.app.advice.LogAroundAdvice"/>
<bean id="logThrowingAdvice" class="cn.xue.app.advice.LogThrowingAdvice"/>

<!-- 定义事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--配置事务的传播特性 -->
<!--事务的传播行为
REQUIRED: 业务方法需要在一个事务中运行,如果方法运行时,已经存在一个事务中,那么加入到该事务,否则自己创建一个新事务。
SUPPORTS: 如果业务方法在某个事务范围内被调用,则方法成为该事务的一部分,如果业务方法在事务外被调用,则方法在没有事务的环境下执行。
MANDATORY: 业务方法只能在一个已经存在的事务中进行,业务方法不能发起自己的事务,如果方法在没有事务的环境中调用,那么容器会抛出例外。
REQUIRESNEW: 不管是否存在事务,业务方法总为自己发起一个新事务;如果方法已经运行在一个事务中,则原有事务会被挂起,新的事务会被创建,直到方法调用结束,新事务才结束,原先的事务再恢复执行。
NOT_SUPPORTED: 声明方法不需要事务,如果方法没有关联到事务,容器不会为它开启事务,如果方法在一个事务中被调用,该事务会被挂起,在方法调用结束后,原先的事务便会恢复执行。
NEVER: 业务方法绝对不能再事务范围内执行,如果方法在某个事务中执行,容器会抛出例外,只有业务方法没有关联到任何事务,方法才能够正常执行。
NESTED: 如果一个活动的事务存在,则运行在一个嵌套的事务中,如果没有活动事务,则按照REQUIRED属性执行,它使用了一个单独的事务,这个事务有多个可以回滚的保存点,
内部事务的回滚不会对外部事务产生影响。它只对DataSourceTransactionManager事务管理器有效。
-->
<!--事务的隔离级别,注:Spring中事务的隔离级别是由数据库实现的
ISOLATION_DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应
ISOLATION_READ_UNCOMMITTED 这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读
ISOLATION_READ_COMMITTED 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。
ISOLATION_REPEATABLE_READ 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。
脏读: 一个事务读取到另一个事务未提交的更新数据。
不可重复读: 在同一事务中,多次读取同一数据返回的结果有所不同,即后续读取可以读取到另一事务已提交的更新数据;相反,"可重复读"是指在同一事务中多次读取数据时,能够保证所读取的数据是一样,即后续读取不能读到另一事务已提交的数据。
幻读: 一个事务读取到另一事务已提交的insert数据。
-->
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: