AOP: 面向切面编程(Aspect Oriented Programming),和Java结构中的OOP是截然不同两种的逻辑,可以理解为是对OOP的一种补充,对程序结构的另一种思考。
在OOP的一等公民是类(Class),而在AOP中则是切面(Aspect),AOP典型应用就是事务管理器。
其实在Spring IoC 容器并不依赖于AOP,所以你可以在IoC中不使用AOP,但是在 Spring 使用AOP 提供了非常方面的支持。
本文将简单介绍AOP用法,包括各个名词定义与举例。
本文大部分知识点,来源于Spring 官方文档:https://docs.spring.io/spring/docs/2.5.x/reference/aop.html
例子
下面是在Spring 中,定义一个切面:
@Aspect
public class WorldAop implements Ordered {
@Pointcut("execution(* com.anla.springaop.service.*.*(..))")
private void returnPointcut() {
}
@Before("returnPointcut()")
public void doBefore(JoinPoint joinPoint) {
String apiName = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
System.out.println("========== 调用方法WorldAop:{} start ==========, " + apiName);
for (Object arg : joinPoint.getArgs()) {
System.out.println("arg:," + arg);
}
System.out.println("========== 调用方法WorldAop:{} end ==========, " + apiName);
}
@Around("returnPointcut()")
public Object interceptor(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("pjp is :" + pjp);
return pjp.proceed();
}
@Override
public int getOrder() {
return 10;
}
}
@Aspect
@Aspect
注解,表明这个类是个切面。
例如:
@Aspect
public class NotVeryUsefulAspect {
}
@Pointcut
@Pointcut
定义一个切入点,可以理解为正则表达式,即类方法方法执行点的表达式。
实际上,AOP切点支持在任意位置切入,但是Spring AOP 只支持部分 PointCut表达式:
execution
用于匹配方法的切入点within
限制切点为某一些特定的类型。即对Spring 切入点的所有方法this
限定当前执行的方法的 bean实例 是某一种类型target
限制执行放的类型是某一种类型,和上一种来说是对比方法不同,使用this和使用target。args
限制执行的方法,参数是怎样的@target
: 限制切入点,这个类具有某一种类型的注解@args
: 限制方法的参数,是使用什么样的注解@within
:@annotation
: 限制切入点,方法有 这个注解时候会被拦截
执行阶段切面
这里包括这几种注解:@Before
, @AfterReturning
, @AfterThrowing
, @Around
等几种。
分别是代表 方法执行前后的逻辑(@Before
, @AfterReturning
),以及 报错后的逻辑@AfterThrowing
,
方法执行前后的逻辑,包括前和后 @Around
。
例如 下面 @Around
例子:
@Aspect
public class ConcurrentOperationExecutor implements Ordered {
private static final int DEFAULT_MAX_RETRIES = 2;
private int maxRetries = DEFAULT_MAX_RETRIES;
private int order = 1;
public void setMaxRetries(int maxRetries) {
this.maxRetries = maxRetries;
}
public int getOrder() {
return this.order;
}
public void setOrder(int order) {
this.order = order;
}
// Around 类型切面
@Around("com.xyz.myapp.SystemArchitecture.businessService()")
public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
int numAttempts = 0;
PessimisticLockingFailureException lockFailureException;
do {
numAttempts++;
try {
return pjp.proceed();
}
catch(PessimisticLockingFailureException ex) {
lockFailureException = ex;
}
}
while(numAttempts <= this.maxRetries);
throw lockFailureException;
}
}
如果切面需要状态?
如果切面不是单例的,需要状态怎么做?
例如熔断降级,需要监控每一个方法,他们有不同状态,Spring AOP提供了一种基于类似于原型模式方法:
@Aspect("perthis(com.xyz.myapp.SystemArchitecture.businessService())")
public class MyAspect {
private int someState;
@Before(com.xyz.myapp.SystemArchitecture.businessService())
public void recordServiceUsage() {
// ...
}
}
即使用 @Aspect("perthis(com.xyz.myapp.SystemArchitecture.businessService())")
这种方式去声明一个切面,那么每一个切入点都会有一个切面了。
参考:
觉得博主写的有用,不妨关注博主公众号: 六点A君。
哈哈哈,一起研究Spring: