Spring|浅谈AspectJ框架

目录
AspectJ框架
【Spring|浅谈AspectJ框架】AspectJ常见通知类型
AspectJ 的切入点表达式(掌握)
AspectJ的前置通知@Before
前置方式通知注释的实现
前置通知方式参数jionpoint解析
AspectJ框架切换JDK动态代理和CGLib动态代理

AspectJ框架 Spring|浅谈AspectJ框架
文章图片

AspectJ 是一个面向切面的框架,他定义了 AOP 的一些语法,有一个专门的字节码生成器来生成遵守 java 规范的 class 文件。
Spring|浅谈AspectJ框架
文章图片

AspectJ 的通知类型不仅包括我们之前了解过的四种通知:前置通知、后置通知、环绕通知和异常通知,而且还多出一种最终通知即无论程序是否正常执行,最终通知的代码会得到执行。
原因就是切入点表达式,切入点表达式可以标识切面织入到哪些类的那些方法当中,就不需要像我们之前利用 spring 实现 AOP 那样各种配置。只要把切面的实现配置好了,再把这个切入点表达式写好就可以了。

AspectJ常见通知类型
AspectJ 中常用的通知有四种类型:
Spring|浅谈AspectJ框架
文章图片

Spring|浅谈AspectJ框架
文章图片

Spring|浅谈AspectJ框架
文章图片

Spring|浅谈AspectJ框架
文章图片

1)前置通知@Before
2)后置通知@AfterReturning
3)环绕通知@Around
4)最终通知@After
5)定义切入点@Pointcut(了解)

AspectJ 的切入点表达式(掌握)
规范的公式:
execution(访问权限 方法返回值 方法声明(参数) 异常类型)
简化后的公式:
execution( 方法返回值 方法声明(参数) )

用到的符号:
*代码任意个任意的字符(通配符)
..如果出现在方法的参数中,则代表任意参数
如果出现在路径中,则代表本路径及其所有的子路径
示例:
execution(public * *(..)) :任意的公共方法
execution(* set*(..)):任何一个以“set”开始的方法
execution(* com.xyz.service.impl.*.*(..)):任意的返回值类型,在com.xyz.service.impl包下的任意类的任意方法的任意参数
execution(* com.xyz.service..*.*(..)):任意的返回值类型 ,在com.xyz.service及其子包下的任意类的任意方法的任意参数
com.xyz.service.a.b.*.*(..)com.xyz.service.*.*(..)
execution(* *..service.*.*(..)):service之前可以有任意的子包
execution(* *.service.*.*(..)):service之前只有一个包

AspectJ的前置通知@Before
在目标方法执行前切入切面功能.在切面方法中不可以获得目标方法的返回值,只能得到目标方法的签名。
实现的步骤:
添加依赖

org.springframework
spring-aspects
5.2.5.RELEASE

1)创建业务接口
2)创建业务实现
3)创建切面类,实现切面方法
4)在applicationContext.xml文件中进行切面绑定
Spring|浅谈AspectJ框架
文章图片


项目案例:
@Aspect//交给AspectJ的框架去识别切面类
@Component
public class MyAspect {
/**
* 所有切面的功能都是由切面方法来实现的
* 可以将各种切面都在此类中进行开发
*
* 前置通知的切面方法的规范
* 1)访问权限是public
* 2)方法的返回值是void
* 3)方法名称自定义
* 4)方法没有参数,如果有也只能是JoinPoint类型
* 5)必须使用@Before注解来声明切入的时机是前切功能和切入点
*参数:value指定切入点表达式
*
* 业务方法
* public String doSome(String name, int age)
*/
@Before(value = "https://www.it610.com/article/execution(public String com.bjpowernode.s01.SomeServiceImpl.*(String,int))")
public void myBefore(){
System.out.println("切面方法中的前置通知功能实现............");
}
@Before(value = "https://www.it610.com/article/execution(public * com.bjpowernode.s01.SomeServiceImpl.*(..))")
public void myBefore(){
System.out.println("切面方法中的前置通知功能实现............");
}
@Before(value = "https://www.it610.com/article/execution( * com.bjpowernode.s01.*.*(..))")
public void myBefore(JoinPoint jp){
System.out.println("切面方法中的前置通知功能实现............");
System.out.println("目标方法的签名:"+jp.getSignature());
System.out.println("目标方法的参数:"+ Arrays.toString(jp.getArgs()));
}
@Before(value = "https://www.it610.com/article/execution( * com.bjpowernode.s01..*(..))")
public void myBefore(){
System.out.println("切面方法中的前置通知功能实现............");
}
@Before(value = "https://www.it610.com/article/execution( * *(..))")
public void myBefore(){
System.out.println("切面方法中的前置通知功能实现............");
}
}
前置方式通知注释的实现 Spring|浅谈AspectJ框架
文章图片

Spring|浅谈AspectJ框架
文章图片
Spring|浅谈AspectJ框架
文章图片

前置通知方式参数jionpoint解析 Spring|浅谈AspectJ框架
文章图片



AspectJ框架切换JDK动态代理和CGLib动态代理 Spring|浅谈AspectJ框架
文章图片


===>默认是JDK动态代理,取时必须使用接口类型

==>设置为CGLib子类代理,可以使用接口和实现类接


记住:使用接口来接,永远不出错。


    推荐阅读