Spring-AOP-配置

Spring-AOP-配置

spring-AOP-配置

1、步骤

1.1、创建一个接口PersonDao
1.2、创建一个目标类PersonDaoImpl
1.3、创建一个事务Transaction
1.4、把目标类和事务放入到spring容器中
1.5、进行aop的配置
1.5.1、引入aop的命名空间
1
2
3
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.5.2、把PersonDao和Transaction放入到spring容器中
1
2
<bean id="personDao" class="..."></bean>
<bean id="transaction" class="..."></bean>
1.5.3、进行aop的配置
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<aop:config>
<!--
切入点表达式
id为该切面点表达式的唯一标示
-->
<aop:pointcut expression="execution(* com.yc.spring.PersonDaoImpl.*(..))"
id="perform"/>
<!--
一个aspect代表一个切面
-->
<aop:aspect ref="transaction">
<!--
前置通知:
1、在目标方法执行之前执行;
2、在前置通知中有一个参数:JoinPoint,该参数可以获取目标方法的一些信息;
-->
<aop:before method="beginTransaction" pointcut-ref="perform"/>
<!--
后置通知
1、在目标方法执行之后;
2、如果目标方法遇到异常,则后置通知将不在执行;
3、方法中也有两个参数:
JoinPoint:
Object:该参数的名称要与returing配置的参数名称一致
4、能够获取目标方法的返回值;
-->
<aop:after-returning method="commit" pointcut-ref="perform" returning="obj"/>
<!--
最终通知
无论目标方法是否遇到异常,都会执行
-->
<aop:after method="finallyMethod" pointcut-ref="perform"/>
<!--
异常通知
1、获取目标方法获取的异常信息
2、throwing="ex",异常通知中的异常的名称必须是ex
-->
<aop:after-throwing method="throwingMethod" pointcut-ref="perform" throwing="ex"/>
<!--
环绕通知
1、控制目标方法的执行;
2、该方法中有一个ProceedingJoinPoint参数;
3、该参数的proceed()方法调用的是目标方法,,如果该方法不调用,则目标方法不会执行;
4、可以从ProceedingJoinPoint中得到目标方法的一些信息;
5、需要返回时,环绕通知方法也需要返回
6、环绕通知和前置通知/后置通知一般不同时存在
7、前置通知和后置通知不能控制目标方法的执行;
-->
<aop:around method="aroundMethod" pointcut-ref="perform"/>
</aop:aspect>
</aop:config>

2、原理:

  • 1、启动spring容器,把personDao和transaction实例化
  • 2、当spring容器解析到aop:config配置的时候,会解析切入点表达式
  • 3、把切入点表达式解析出来以后,和spring容器中的bean做匹配,如果匹配成功,则为该bean创建代理对象;
  • 4、代理对象的方法的创建过程就把通知和目标方法结合在一起了
  • 5、当在客户端执行context.getBean时,先检查跟bean是否有代理对象,如果有代理对象,则返回代理对象;如果没有代理对象,则返回对象本身
    注意:如果切入点表达式在spring容器中没有找到匹配的对象,则会报错

3、切入点配置说明

下面是spring切入点的配置说明:

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

直接看的话,还是不是很好理解
通过一个方法声明的来对比说明一下:

1
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException

修饰符类型 返回值类型 声明类型 方法名 参数类型 异常类型
modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern param-pattern throws-pattern?
public void java.lang.Object wait long throws java.lang.InterruptedException

切入点配置举例:
execution (public (..) ) : 表示任意公共方法
execution ( set(..) ) : 表示以set开头的任意方法
execution ( com.xyz.service.AccountService.(..) ) : 表示com.xyz.service.AccountService类中的所有方法
execution ( com.xyz.service..(..) ) :表示com.xyz.service包下的所有的类的所有的方法
execution (
com.xyz.service...(..) ) :表示com.xyz.service包下及其子包下的所有的类的所有的方法