切面的创建方法,使用
1. 相关术语
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...."); }
}
|
扫描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
| <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" />
|