一、环绕注解
环绕注解
环绕注解@Aroud
注解 | 描述 |
---|---|
@Around | @Around是Spring AOP中的一种通知类型,用于在目标方法执行前后进行环绕操作。它可以在方法调用前后增加额外的逻辑,例如日志记录、性能监控等。@Around注解需要配合AspectJ表达式来指定切入点,定义切面类的方法,并在方法内部通过ProceedingJoinPoint参数来控制目标方法的执行流程。 |
环绕注解,通过环绕注解可以实现对增强的整合。
对于环绕注解需要创建ProceedingJoinPoint对象并需要使用连两个对应方法
方法 | 描述 |
---|---|
proceed() | 执行被通知的目标方法,并返回其返回值。在环绕通知中必须调用此方法,否则目标方法不会执行。 |
getArgs() | 获取目标方法的参数值数组。返回的参数数组是Object类型的。 |
环绕注解使用案例:
@Component
@Aspect
public class RoundAdvice {
@Around("com.alphamilk.Advice.MyPointcut.pointcut1()")
public Object Transation(ProceedingJoinPoint joinPoint){
// 获取方法参数
Object[] args = joinPoint.getArgs();
// 获取返回值
Object result = null;
try {
System.out.println("事务开始");
// 执行对应方法
result = joinPoint.proceed(args);
System.out.println("事务结束");
} catch (Throwable e) {
System.out.println("事务回滚");
throw new RuntimeException(e);
}
return result;
}
}
注意:使用增强需要开启通知注解
@ComponentScan(value = "com.alphamilk")
@Configuration
//开启增强注解
@EnableAspectJAutoProxy
public class JavaConfig {
}
而如果不是使用环绕注解,则需要使用@Before @After @AfterReturning等
@Component
@Aspect
public class advice {
@Before("com.alphamilk.Advice.MyPointcut.pointcut1()")
public void Before(JoinPoint joinPoint) {
System.out.println("事务开始");
}
@After("com.alphamilk.Advice.MyPointcut.pointcut1()")
public void After(JoinPoint joinPoint) {
System.out.println("事务结束");
}
@AfterReturning(value = "com.alphamilk.Advice.MyPointcut.pointcut1()",returning = "result")
public void AfterReturning(JoinPoint joinPoint,Object result) {
System.out.println("调用拥有返回值的方法");
}
@AfterThrowing(value = "com.alphamilk.Advice.MyPointcut.pointcut1()",throwing = "throwable")
public void AfterThrowing(JoinPoint joinPoint,Throwable throwable) {
System.out.println("调用有异常的方法");
}
}
使用环绕注解的优缺点
优点:
- 灵活性高:环绕注解提供了最大程度的灵活性,可以在目标方法执行前后插入额外的逻辑代码,对方法的执行过程进行全面控制。
- 统一处理:通过环绕注解,可以将通用的逻辑代码抽取到切面中,实现统一的处理逻辑,避免在各个目标方法中重复编写相同的代码。
- 可以修改返回值:在环绕通知中,可以通过修改目标方法的返回值来影响最终的结果。
缺点:
- 复杂性增加:相对于其他类型的通知,环绕注解的使用稍显复杂,需要更多的理解和掌握,特别是对于ProceedingJoinPoint的使用。
- 性能开销:由于环绕注解会包裹整个目标方法的执行流程,在某些情况下可能会带来一定的性能开销,特别是处理逻辑较为复杂的情况。
- 可能引入副作用:在环绕通知中对目标方法做任意修改时,需要谨慎操作,避免引入不可预料的副作用,导致程序出现异常或不正常的行为。
二、优先级注解
注解 | 描述 |
---|---|
@Order | @Order是Spring框架中用于定义组件的加载顺序的注解。它可以用在类级别或方法级别上。当多个组件都实现了同一个接口或继承了同一个父类时,通过@Order注解可以指定它们的加载顺序。@Order的值越小,优先级越高,具有更高的加载顺序。@Order注解的值可以是任意整数。需要注意的是,相同优先级的组件加载顺序是不确定的,所以最好将优先级设置为不同的值来避免不确定性。 |
如果对于同一个方法有两种甚至多种增强,并且需要指定增强的循序,则需要使用@Order优先级注解来设置。
对于其使用,核心在于:指定一个优先级,Order的值越低越是优先,越高优先级前置先执行,后置后执行
案例代码:(第一个增强)
@Component
@Aspect
//设置一个优先级更高注解
@Order(10)
public class advice {
@Before("com.alphamilk.Advice.MyPointcut.pointcut1()")
public void Before(JoinPoint joinPoint) {
System.out.println("优先级高前置执行");
}
@After("com.alphamilk.Advice.MyPointcut.pointcut1()")
public void After(JoinPoint joinPoint) {
System.out.println("优先级高后置后执行");
}
@AfterReturning(value = "com.alphamilk.Advice.MyPointcut.pointcut1()",returning = "result")
public void AfterReturning(JoinPoint joinPoint,Object result) {
System.out.println("调用拥有返回值的方法");
}
@AfterThrowing(value = "com.alphamilk.Advice.MyPointcut.pointcut1()",throwing = "throwable")
public void AfterThrowing(JoinPoint joinPoint,Throwable throwable) {
System.out.println("调用有异常的方法");
}
}
第二个增强
@Component
@Aspect
@Order(20)
public class RoundAdvice {
@Around("com.alphamilk.Advice.MyPointcut.pointcut1()")
public Object Transation(ProceedingJoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
Object result = null;
try {
System.out.println("优先级低前置后执行");
// 执行对应方法
result = joinPoint.proceed(args);
System.out.println("优先级低后置先执行");
} catch (Throwable e) {
System.out.println("事务回滚");
throw new RuntimeException(e);
}
return result;
}
}