各个注解方法执行顺序
@Around注解方法的前半部分业务逻辑->@Before注解方法的业务逻辑->目标方法的业务逻辑
->@Around注解方法的后半部分业务逻辑(@Around注解方法内的业务逻辑若对ProceedingJoinPoint.proceed()方法没做捕获异常处理,直接向上抛出异常,则不会执行Around注解方法的后半部分业务逻辑;若做了异常捕获处理,则会执行)。
->@After(不管目标方法有无异常,都会执行@After注解方法的业务逻辑)
->@AfterReturning(若目标方法无异常,执行@AfterReturning注解方法的业务逻辑)
->@AfterThrowing(若目标方法有异常,执行@AfterThrowing注解方法的业务逻辑)
环绕通知@Around使用
/**
* 此方法必须有返回值,否则目标方法无法拿到执行结果
* @param point
* @return
*/
@Around("execution(* com.test.resultFacade..*(..))")
public Object checkContactInfoUpdateBefore(ProceedingJoinPoint point){
log.info("目标方法前执行");
Object result = null;
try {
// 执行目标方法
result = point.proceed();
log.info("result:",JSONObject.toJSONString(result));
} catch (Throwable throwable) {
throwable.printStackTrace();
}
log.info("目标方法后执行");
return result;
}
aspect各个方法的使用案例说明
@Aspect
@Slf4j
public class MessageAspect {
/**
* 方式一:使用表达式,满足此注解的方法即会执行切面方法
* 1.本类引用
* 2.其他的切面引用
*/
@Pointcut("execution(public Integer com.xiaoz.aop.calculator.dev(int,int))")
public void poincut(){
}
/**
* 方式二:使用主键方式,标注此注解的方法即会执行切面方法
* 1.本类引用
* 2.其他的切面引用
*/
@Pointcut("@annotation(com.xiaoz.annotation.MessageAnnotation)")
public void pointcut() {
}
/**
* around切面方法,引用本类中的公用的pointcut
* @param point
* @return
* @throws Throwable
*/
@Around("Pointcut()")
public Object process(ProceedingJoinPoint point) throws Throwable {
System.out.println("@Around:执行目标方法之前...");
//访问目标方法的参数:
Object[] args = point.getArgs();
if (args != null && args.length > 0 && args[0].getClass() == String.class) {
args[0] = "改变后的参数1";
}
//用改变后的参数执行目标方法
Object returnValue = point.proceed(args);
System.out.println("@Around:执行目标方法之后...");
System.out.println("@Around:被织入的目标对象为:" + point.getTarget());
return "原返回值:" + returnValue + ",这是返回结果的后缀";
}
/**
* 引用其他外部切面类的切入点公用方法
*/
@After(com.xiaoz.other.LogAspect.pointCut())
public void logEnd(){
log.info("执行代码");
}
@Before("execution(* com.abc.service.*.many*(..))")
public void permissionCheck(JoinPoint point) {
System.out.println("@Before:模拟权限检查...");
System.out.println("@Before:目标方法为:" +
point.getSignature().getDeclaringTypeName() +
"." + point.getSignature().getName());
System.out.println("@Before:参数为:" + Arrays.toString(point.getArgs()));
System.out.println("@Before:被织入的目标对象为:" + point.getTarget());
}
/**
* 在所有标记了@SMSAndMailSender的方法中切入
* @param joinPoint
* @param result
*/
@AfterReturning(value="@annotation(com.trip.demo.SMSAndMailSender)", returning="result")
public void afterReturning(JoinPoint joinPoint , Object result//注解标注的方法返回值) {
MethodSignature ms = (MethodSignature) joinPoint.getSignature();
Method method = ms.getMethod();
boolean active = method.getAnnotation(SMSAndMailSender.class).isActive();
if (!active) {
return;
}
String smsContent = method.getAnnotation(SMSAndMailSender.class).smsContent();
String mailContent = method.getAnnotation(SMSAndMailSender.class).mailContent();
String subject = method.getAnnotation(SMSAndMailSender.class).subject();
}
/**
* 在抛出异常时使用 SMSAndMailSender为自定义注解,所有标注此注解的业务方法都会触发此切面方法
* @param joinPoint
* @param ex
*/
@AfterThrowing(value="@annotation(com.xiaoz.SMSAndMailSender)",throwing = "ex")
public void afterThrowing(JoinPoint joinPoint, Throwable ex//注解标注的方法抛出的异常) {
MethodSignature ms = (MethodSignature) joinPoint.getSignature();
Method method = ms.getMethod();
String subject = method.getAnnotation(SMSAndMailSender.class).subject();
}
}
使用annotation生产代码案例
自定义注解类
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MessageAnnotation {
InteractionTopicEnum value();
}
自定义枚举类
@Getter
@AllArgsConstructor
public enum InteractionTopicEnum {
ORDER(1, "下单完成"),
ORDER_PAY(2, "支付完成"),;
private Integer key;
private String value;
}
业务方法标注切面方法
@Transactional
@MessageAnnotation(InteractionTopicEnum.ORDER)
public BaseDtoResponse<Boolean> creatOrder(){
// 执行业务代码
}
切面类方法
@Aspect
@Slf4j
public class MessageAspect {
@Pointcut("@annotation(com.xiaoz.annotation.MessageAnnotation)")
public void pointcut() {
}
@Before("pointcut()")
public void permissionCheck(JoinPoint point) {
// 执行切入方法
}
}
版权声明:本文为qq_36042938原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。