SpringBoot开发随记--AOP的使用
Aop原理
1、什么是Aop
aop 全称 Aspect Oriented Programming,面向切面,AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。其与设计模式完成的任务差不多,是提供另一种角度来思考程序的结构,来弥补面向对象编程的不足。
AOP技术利用一种称为“横切”的技术,解剖封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,这样就能减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。
2、AOP常用术语
-
切面Aspect-----通常是一个类,里面可以定义切入点和通知
一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是J2EE应用中一个关于横切关注点的很好的例子。在Spring AOP中,切面可以使用基于模式或者基于@Aspect注解的方式来实现。 -
连接点Joinpoint
在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。在Spring AOP中,一个连接点总是表示一个方法的执行。 -
通知Advice
在切面的某个特定的连接点上执行的动作。其中包括了“around”、“before”和“after”等不同类型的通知(通知的类型将在后面部分进行讨论)。许多AOP框架(包括Spring)都是以拦截器做通知模型,并维护一个以连接点为中心的拦截器链 -
切入点Pointcut
匹配连接点的断言。通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行(例如,当执行某个特定名称的方法时)。切入点表达式如何和连接点匹配是AOP的核心:Spring缺省使用AspectJ切入点语法。 -
引入introduction
用来给一个类型声明额外的方法或属性(也被称为连接类型声明(inter-type declaration))。Spring允许引入新的接口(以及一个对应的实现)到任何被代理的对象。例如,你可以使用引入来使一个bean实现IsModified接口,以便简化缓存机制。 -
**目标对象Target Object **
被一个或者多个切面所通知的对象。也被称做被通知(advised)对象。既然Spring AOP是通过运行时代理实现的,这个对象永远是一个被代理(proxied)对象。 -
Aop代理
AOP框架创建的对象,用来实现切面契约(例如通知方法执行等等)。在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。 -
织入 Weaving
把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。这些可以在编译时(例如使用AspectJ编译器),类加载时和运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。
3、AOP execution表达式语法
execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)
- 表达式示例:execution(* com.package..*. * (..))
标识符 | 含义 |
---|---|
execution() | 表达式的主体 |
第一个“*”符号 | 表示返回值的类型任意 |
com.package | AOP所切的服务的包名,即,需要进行横切的业务类 |
包名后面的“..” | 表示当前包及子包 |
第二个“*” | 表示类名,*即所有类 |
.*(..) | 表示任何方法名,括号表示参数,两个点表示任何参数类型 |
不同维度的描述
- 通过注解定义切点
- @annotation( 注解的路径)
- 通过方法修饰符定义切点
匹配所有的public修饰符的方法:
- execution(public * *(..))
- 通过方法名定义切点
匹配所有”set”开头的方法:
- execution(* set*(..))
- 通过类定义切点
匹配AccountService 接口的所有方法:
- execution(* com.xyz.service.AccountService.*(..))
- 通过包定义切点
匹配service包中的所有类的方法:
- execution(* com.xyz.service.*(..))
匹配service包及其子包中的所有方法:
- execution(* com.xyz.service..*(..))
4、AOP通知类型
1、Before:在目标方法被调用之前做增强处理,@Before只需要指定切入点表达式即可
2、AfterReturning:在目标方法正常完成后做增强,@AfterReturning除了指定切入点表达式后,还可以指定一个返回值形参名returning,代表目标方法的返回值
3、AfterThrowing:主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还可以指定一个throwing的返回值形参名,可以通过该形参名来访问目标方法中所抛出的异常对象
4、After:在目标方法完成之后做增强,无论目标方法时候成功完成。@After可以指定一个切入点表达式
5、Around:环绕通知,在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint
代码示范
@Component
@Aspect
public class AOPTest {
/**
* 定义一个切入点
*/
@Pointcut("execution(* cn.hhu..bbs..*.*(..))")
public void pointcut1(){}
@Before("pointcut1()")
public void before(JoinPoint joinPoint){
System.out.println("before");
}
@After("pointcut1()")
public void after(JoinPoint joinPoint){
System.out.println("after");
}
@AfterReturning(pointcut = "pointcut1()",returning = "returnVal")
public void afterReturning(JoinPoint joinPoint,Object returnVal){
System.out.println("afterReturning:result+"+returnVal);
}
@Around("pointcut1()")
public void around(ProceedingJoinPoint proceedingJoinPoint){
System.out.println("around 前");
try {
proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("around后");
}
}
around 前
before
执行方法体
around后
after
afterReturning:result+null
网友评论