AOP切面类使用代码

各个注解方法执行顺序

@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版权协议,转载请附上原文出处链接和本声明。