- schema-defined aspects只支持singleton model,即:所有基于配置文件的切面只支持单例模式
- Spring所有的切面和通知器都必须放在一个
<aop:config>
内(可以配置包含多个<aop:config>
元素),每一个<aop:config>
可以包含pointcut
,advisor
和aspect
元素(必须按照以上顺序进行声明) <aop:config>
风格的配置大量使用了Spring的自动代理机制
切面(Aspect)
1 | <beans xmlns="http://www.springframework.org/schema/beans" |
切入点(Pointcut)
首先,介绍这里使用的一些基本通配符的含义
* : 匹配任意数量的字符
+ :匹配制定数量的类及其子类
.. :匹配本包
… :匹配本包及其子包
- execution(权限类型)
- execution(public* *(..))
切入点为执行所有public方法时
- execution(* set*(..))
切入点为执行所有set开始的方法时
- execution(* com.xyz.service.AccountService.*(..))
切入点为执行AccountService类中的所有方法时
- execution(* com.xyz.service..(..))
切入点为执行com.xyz.service包下的所有方法时
- execution(* com.xyz.service…(..))
切入点为执行com.xyz.service包及其子包下的所有方法时
以下,Only in Spring AOP
- within(com.xyz.service.*)
- within(com.xyz.service..*)
within 用于匹配指定类型内的方法执行
- this(com.xyz.service.AccountService)
this 用于匹配当前AOP代理对象类型的执行方法
- target(com.xyz.service.AccountService)
target用于匹配当前目标对象类型的执行方法
- args(java.io.Serializable)
args用于匹配当前执行的方法传入的参数为指定类型的执行方法
- @target(org.springframework.transaction.annotation.Transactional)
- @within(org.springframework.transaction.annotation.Transactional)
- @annotation(org.springframework.transaction.annotation.Transactional)
- @args(com.xyz.security.Classified)
- bean(tradeService)
- bean(*Service)
1 |
|
通知(Advice)
名称 | 说明 |
---|---|
前置通知(Before advice) | 在某连接点(join point)之前执行的通知,但不能阻止连接点前的执行(除非它抛出一个异常) |
返回后通知(After returning advice) | 在某连接点(join point)完成后执行的通知(不论是正常返回还是异常退出) |
抛出异常后通知(After throwing advice) | 在方法抛出异常退出时执行的通知 |
后通知(After(finally)advice) | 当某连接点退出的时候执行的通知 |
环绕通知(Around Advice) | 包围一个连接点(join point)的通知 |
1 | try { |
1 |
|
Around advice
通知方法的第一个参数必须是
ProceedingJoinPoint
类型.xml
1
2
3
4
5
6<aop:config>
<aop:aspect ref="myAspect" id="myAspectAOP">
<aop:around method="around" pointcut="execution(* aop.schema.MyBiz.*(..))"/>
</aop:aspect>
</aop:config>.
.java
1
2
3
4
5
6
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
// start stopwatch
Object retVal = pjp.proceed();
// stop stopwatch
return retVal;
}
测试所用代码
业务对象
MyBiz2
1
2
3
4
5
6
7
8
9
10
11package aop.schema.around;
public class MyBiz2 {
public void biz() {
System.out.println("MyBiz:biz()");
// throw new RuntimeException();
}
public void init(String bizName, int times) {
System.out.println("MyBiz:init()" + " bizName:" + bizName + " times:" + times);
}
}切面对象
MyParametersAdvice
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30package aop.schema.around;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyParametersAdvice {
public Object around(ProceedingJoinPoint pjp, String bizName, int times) throws Throwable {
System.out.println("MyParametersAdvice:around()" + " bizName:" + bizName + " times:" + times);
System.out.println("MyParametersAdvice: around() FirstPrint");
Object obj = pjp.proceed();
System.out.println("MyParametersAdvice: around() SecondPrint");
return obj;
}
public void before() {
System.out.println("MyParametersAdvice:before()");
}
public void afterReturning() {
System.out.println("MyParametersAdvice:afterReturning()");
}
public void afterThrowing() {
System.out.println("MyParametersAdvice:afterThrowing()");
}
public void after() {
System.out.println("MyParametersAdvice:after()");
}
}Spring配置文件
schema-around.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="myParametersAdvice" class="aop.schema.around.MyParametersAdvice"/>
<bean id="myBiz2" class="aop.schema.around.MyBiz2"/>
<aop:config>
<aop:aspect id="myParametersAdviceAOP" ref="myParametersAdvice">
<aop:pointcut id="myPointcut" expression="execution(* aop.schema.around.MyBiz2.*(..))"/>
<aop:before method="before" pointcut-ref="myPointcut"/>
<aop:after-returning method="afterReturning" pointcut-ref="myPointcut"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="myPointcut"/>
<aop:after method="after" pointcut-ref="myPointcut"/>
<aop:around method="around"
pointcut="execution(* aop.schema.around.MyBiz2.init(String,int)) and args(bizName,times)"/>
</aop:aspect>
</aop:config>
</beans>测试类
parametersAdviceTest
其继承的UnitTestBase
在 Spring中使用JUnit4的过度方法 中给出1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21package AOP.around;
import aop.schema.around.MyBiz2;
import beans.UnitTestBase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
public class parametersAdviceTest extends UnitTestBase {
public parametersAdviceTest() {
super("AOP/schema-around.xml");
}
public void test(){
MyBiz2 myBiz2 = super.getBean("myBiz2");
myBiz2.biz();
System.out.println("*******************");
myBiz2.init("testString",2);
}
}控制台输出结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14MyParametersAdvice:before()
MyBiz:biz()
MyParametersAdvice:after()
MyParametersAdvice:afterReturning()
*******************
MyParametersAdvice:before()
MyParametersAdvice:around() bizName:testString times:2
MyParametersAdvice: around() FirstPrint
MyBiz:init() bizName:testString times:2
MyParametersAdvice: around() SecondPrint
MyParametersAdvice:after()
MyParametersAdvice:afterReturning()
Process finished with exit code 0