AOP是Aspect Oriented Programming的缩写,即”面向切面编程“。
AOP相关概念
重点是切点、通知和切面。
抽象概念 | 解释 |
---|---|
Target | 代理的目标对象。 |
Proxy | 一个类被AOP织入增强后,就产生了一个结果代理类。 |
JoinPoint(连接点) | 所谓连接点是指那些被拦截到的点。在springAOP中,这些点指的是方法,因为spring只支持方法类型的连接点。 |
Pointcut(切点) | 所谓切入点是指我们要对哪些连接点进行拦截的定义,AOP通过切点定位特定的连接点。 |
Advice(通知) | 所谓通知是指拦截到连接点之后所要做的事情。 |
Aspect(切面) | 是切入点和通知的结合,通常由一个拦截器类来表示。 |
Weaving | 是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入。 |
注:连接点和切入点可以理解为一个班级中“学生“和”班干部“的联系,所有的学生(包括班干部)都可以视为是连接点,而班干部(特定的学生)可以视为是切入点。
具体以SpringAOP(或者说是AspectJ)举例说明:
//AnnotationPointCut类相当于一个切面
@Aspect
public class AnnotationPointCut {
//com.zy.service.UserSerciceImpl.*(..))相当于切入点的定义,此表达式说明UserSerciceImpl类下的所有方法都为切入点。
@Before("execution(* com.zy.service.UserSerciceImpl.*(..))")
public void before(){
System.out.println("=========before========");
}
//Before、After和Around等注解相当于“通知”
@After("execution(* com.zy.service.UserSerciceImpl.*(..))")
public void after(){
System.out.println("===========after===========");
}
@Around("execution(* com.zy.service.UserSerciceImpl.*(..))")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕前");
Object proceed = joinPoint.proceed();
System.out.println("环绕后");
}
}
切点表达式的写法
表达式语法:
execution([修饰符]返回值类型 包名.类名.方法名(参数))
- 访问修饰符可以省略
- 返回值类型、包名、类名、方法名可以使用星号
*
代表任意 - 包名与类名之间一个点
.
代表当前包下的类,两个点..
代表当前包及其子包下的类 - 参数列表可以使用两个
..
表示任意个数,任意类型的参数列表
例如:
execution(public void com.zy.aop.Target.method()) //具体的方法(如果属于public void,则可省略)
execution(com.zy.aop.Target.*(..)) //Target方法下的任意方法且任意参数
execution(* com.zy.aop.*.*(..)) //返回值类型任意,aop包下的任意类的任意方法任意参数
execution(* com.zy.aop..*.*(..)) //返回值类型任意,aop包及其子包下的任意类的任意方法任意参数
execution(* *..*.*(..)) //都任意
通知的五种类型
通知类型 | 说明 |
---|---|
前置通知(Before) | 在目标方法被调用之前调用通知功能。 |
后置通知(After) | 在目标方法完成之后调用通知,此时不会关心方法是否成功执行。 |
返回通知(After-returning) | 在目标方法成功执行之后调用通知。 |
异常通知(After-throwing) | 在目标方法抛出异常后调用通知。 |
环绕通知(Around) | 通知包裹了被通知的方法,在被通知的方法调用之前和之后执行自定义的行为。 |
写在最后
网上看到很多关于”连接点“和”切入点“的解释并不完全相同,本文的解释仅为我结合一些资料总结出的个人的理解,大家要带有思考的来看待这些解释。
其余参考: