SpringAop的使用,使用xml和@注解配置两种方式
需要jar包:
AOP执行顺序:
前置通知,是在方法前执行吗?
环绕通知执行,进入方法...
执行save()方法...
@后置通知,是在方法后执行吗?
最终通知 执行...
@异常通知,程序出现异常了吗?(出现异常通知则后置通知不执行)
环绕通知,退出方法...
========================================================
第一步:使用注解方式建立切面类,代码如下:
package com.newer.test;
import java.lang.reflect.Method;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
/**
* 测试Spring AOP机制 <br/>
* 使用注解方式 配置切面 [@Aspect]
* @author RSun
* 2012-2-21上午12:07:17
*/
@Aspect
public class TestAOP {
/**
@SuppressWarnings("unused")
@Pointcut("execution(* com.newer.service.impl.PersonServiceImpl.*(..))")
private void anyMethod(){}
/**
@Before("anyMethod()")
public void doAccessCheck() {
System.out.println("前置通知,是在方法前执行吗?");
}
/**
@Before("anyMethod() && args(name)")
public void doAccessCheckTwo(String name) {
}
/**
@AfterReturning("anyMethod()")
public void doAccessReturning() {
}
/**
@AfterReturning(pointcut="anyMethod()", returning="result")
public void doAccessReturningTwo(String result) {
}
/**
@After("anyMethod()")
public void doAfter() {
}
/**
@AfterThrowing("anyMethod()")
public void doAfterThrowing() {
}
/**
@AfterThrowing(pointcut="anyMethod()", throwing="e")
public void doAfterThrowingTwo(Exception e) {
}
/**
@Around("anyMethod()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕通知 执行,进入方法...");
//获取被拦截的方法
Method method = ((MethodSignature)pjp.getSignature()).getMethod();
System.out.println("method:"+method.getName());
//获取拦截方法的参数
Object[] obj = pjp.getArgs();
for (Object object : obj) {
}
//必须执行这方法,如果后面有切面则先执行切面;
//如果不执行proceed(),则后面的方法和和切面都不执行
Object result = pjp.proceed(); //返回值,可以修改
System.out.println("退出方法...");
return result;
}
}
* 解析:
* @Pointcut("execution(* com.newer.service..*.*(..) ")
* @Pointcut("execution(* com.newer.action..*.user*LoginOut())")
* execution(* com.newer.service..*.*(..) <br/>
* execution(1 com.newer.service..2.3(..) <br/>
* 1. 表示返回值类型,例:java.lang.String,*号代表任何返回类型 ,!void表示必须有返回值
* 2. 表示类,* 号代表对所有类拦截 <br/>
* 3. 表示方法,* 号代表所有方法 <br/>
* 4. service.. 这两个点代表可以对service下的子包进行拦截 <br/>
* 5. (..) 表示方法的参数可以可无,一个也行,多个亦可,例如:(java.lang.String,..)
*
* 注解引用切入点的写法 * @Before("userLogin()")
* @Before("userLogin() && userLoginOut()")
* @Before("execution(* com.vveoss.examination.dailyExam.submitPaper(..))")
========================================================
第二步:xml方式的普通切面类,代码如下:
package com.newer.test;
import org.aspectj.lang.ProceedingJoinPoint;
/**
* 测试Spring AOP机制 <br/>
* 使用xml方式配置
* @author RSun
* 2012-2-21上午12:07:17
*/
public class TestAOPXml {
/*** 注解定义前置通知(方法执行前执行) */
public void doAccessCheck() {
}
/*** 后置通知(方法执行成功后执行) */
public void doAccessReturning() {
}
/*** 最终通知 (finally块) */
public void doAfter() {
}
/**
public void doAfterThrowing() {
}
/**
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("xml-----------环绕通知 执行,进入方法...");
//必须执行这方法,如果后面有切面则先执行切面;
//如果不执行proceed(),则后面的方法和和切面都不执行
Object result = pjp.proceed();
System.out.println("xml-----------退出方法...");
return result;
}
}
==========================
==============================
第三步:applicationContext.xml配置,代码如下:
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<!-- 开启bean注解模式 -->
<context:annotation-config />
<!-- 扫描bean -->
<context:component-scan base-package="com.newer.service" />
<!-- 开启aop注解 -->
<aop:aspectj-autoproxy />
<!-- 切面交由Spring管理 -->
<bean id="testAop" class="com.newer.test.TestAOP" />
<!-- xml方式配置aop -->
<bean id="testAopXml" class="com.newer.test.TestAOPXml" />
<aop:config>
<aop:aspect id="asp" ref="testAopXml">
<!-- 定义切面 -->
<aop:pointcut id="mycut" expression="execution(* com.newer.service.impl.PersonServiceImpl.*(..))" />
<!-- 定义前置通知,关联切面和拦截方法doAccessCheck() -->
<aop:before pointcut-ref="mycut" method="doAccessCheck"/>
<!-- 定义后置通知 -->
<aop:after-returning pointcut-ref="mycut" method="doAccessReturning"/>
<!-- 异常通知 -->
<aop:after-throwing pointcut-ref="mycut" method="doAfterThrowing"/>
<!-- 最终通知 -->
<aop:after pointcut-ref="mycut" method="doAfter"/>
<!-- 环绕通知 -->
<aop:around pointcut-ref="mycut" method="doAround"/>
</aop:aspect>
</aop:config>
</beans>
总结: - 配置好之后,可以使用junit测试,访问相关方法时会被触发。
- 需注意配置细节(只能拦截action、service和dao接口派生出来的方法)。
|