Spring实战-面向切面的Spring

切面的创建方法,使用

1. 相关术语

  • Advice

    通知 :用于多个应用对象的行为 before,after,afterReturning,afterThrowing,around

  • Pointcut

    切点 :通知应用的具体位置,哪些连接点得到通知

  • Join Point

    连接点:潜在目标,能够应用通知的所有点

  • Aspect

    切面:通知+切点

spring仅支持方法级连接点

2. 切点表达式

AspectJ指示器 描述
arg() 匹配参数为指定类型
@args() 匹配参数由指定注解标注
execution() 匹配执行方法
this() 匹配AOP代理的bean引用
target 匹配目标对象
@target() 匹配特定的执行对象
within() 匹配指定类型
@within() 匹配指定注解类型
@annotation 匹配带有指定注解的连接点

execution

注解 描述
@Aspect 声明为切面类
@Pointcut 切点定义
@before 目标方法调用之前执行
@after 目标方法调用之后或抛出异常后执行
@afterReturning 目标方法返回后执行,后于after
@beforeThrowing 目标方法抛出异常后
@Around 将目标方法封装起来

3. 创建切面 - 实战

1
2
3
4
5
6
@Component
public class Method {
public void method(){
System.out.println("create.....");
}
}

切面使用需要导入

aspectjweaver.jar

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
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.springframework.stereotype.Component;

@Aspect
@Component
public class AopTest {

@Pointcut("execution(* Method.method(..))")
public void performance(){}

@Before("performance()")
public void before(){
System.out.println("Before....");
}
@After("performance()")
public void after() {
System.out.println("After....");
}

@AfterReturning("performance()")
public void afterReturning() {
System.out.println("AfterReturning....");
}

@AfterThrowing("performance()")
public void afterThrowing() {
System.out.println("AfterThrowing....");
}

// @Around("performance()")
// public void around() {
// System.out.println("Around....");
// }
}

扫描Component

切面代理需要设置自动代理启用

@EnableAspectJAutoProxy | <aop:aspectj-autoproxy >

1
2
3
4
5
6
@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class Config {

}

测试

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
import static org.junit.Assert.assertNotNull;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=Config.class)
public class Main {
@Autowired
Method method;

@Autowired
AopTest aopTest;

@Test
public void test(){
method.method();
assertNotNull(method);
assertNotNull(aopTest);
}
}

输出

1
2
3
4
Before....
create.....
After....
AfterReturning....

3.1. 环绕通知

包装目标方法 相当于 同时设置前置通知+后置通知

1
2
3
4
5
6
7
8
9
10
@Around("performance()")
public void around(ProceedingJoinPoint jp) {
System.out.println("Around before....");
try {
jp.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("Around after....");
}

输出

Around before….

create…..

Around after….

4. 处理参数

目标方法

1
2
3
4
5
6
@Component
public class Method {
public void method(int a){
System.out.println("create....."+a);
}
}

切面 限定参数类型及参数名

1
2
3
4
5
6
@Pointcut("execution(* Method.method(int)) && args(a)")
public void performance(int a){}

@Before("performance(a)")
public void before(int a){
System.out.println("Before...."+a);

5. 引入新功能

@DeclareParents 将Shopping接口引入到实现People接口的bean中。

value 所有实现People的类

defalutImpl 引入功能提供实现的类,实现了Shopping接口

1
2
3
4
5
6
7
8
9
10
11
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class Test2 {

@DeclareParents(value="People+",defaultImpl=children.class)
public Shopping shopping;
}

6. XML中声明切面

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 自动代理AspectJ注解通知类 -->
<aop:aspectj-autoproxy/>

<aop:config>
<aop:aspect ref="aopTest">
<aop:pointcut id="performance" experssion="execution(* Method.method(..)"/>
<aop:before pointcut-ref="performance" method="before"/>
<aop:after pointcut-ref="performance" method="after"/>
<aop:after-returning pointcut-ref="performance" method="afterReturning"/>
<aop:after-throwing pointcut-ref="performance" method="afterThrowing"/>
<aop:around pointcut-ref="performance" method="around"/>
</aop:aspect>
</aop:config>

aop:declare-parents

此声明所通知的bean要在它的对象层次结构中拥有新的父类型。

类型匹配的People接口的那些bean在父类型结构中会增加Shopping接口。

1
2
3
4
5
<aop:declare-parents
types-matching="People+"
implements-interface="Shopping"
delegate-ref="children"
/>
本文结束  感谢您的阅读