Springboot加Aspectj注解方法实现aop切面

一、准备

1.springboot的demo项目一个。

2.maven的xml配置 ,

spring-boot-starter-web:springboot启动需要的类。
spring-boot-starter-aop:开启aop,必需有,没有完成不了切面。
aspectjrt:切面所需要的类和注解都在里面。
<dependency>
		<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>
<dependency>
		<groupId>org.aspectj</groupId>
		<artifactId>aspectjrt</artifactId>
		<version>1.9.6</version>
	</dependency>

二、实现

1.自定义一个注解

import java.lang.annotation.*;

@Target(value = {ElementType.TYPE,ElementType.METHOD})
@Documented
@Retention(value = RetentionPolicy.RUNTIME)
public @interface DS {
    String value() default "";
}

2.写一个切面类

只要方法上有@DS自定义注解的方法都会被切面类检测到。

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Aspect
@Component
public class AspectAnnotation {

    /**
     * 使用@Before在切入点开始处切入内容
     * @param point
     */
    @Before("@annotation(DS)")
    public void Before(JoinPoint point){
        System.out.println("在切入点开始处切入内容");
    }

    /**
     * 使用@After在切入点结尾处切入内容
     */
   @After("@annotation(DS)")
    public void After(JoinPoint point){
        System.out.println("在切入点结尾处切入内容");
    }

    /**
     * 使用@AfterReturning在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)
     */
    @AfterReturning("@annotation(DS)")
    public void AfterReturning(JoinPoint point){
        System.out.println("在切入点return内容之后切入内容");
    }

    /**
     * 使用@Around在切入点前后切入内容,并自己控制何时执行切入点自身的内容(环绕通知)
     */
    @Around("@annotation(DS)")
    public Object Around(ProceedingJoinPoint pdj){
        /*result为连接点的放回结果*/
        Object result = null;
        String methodName = pdj.getSignature().getName();

        /*前置通知方法*/
        System.out.println("1前置通知方法>目标方法名:" + methodName + ",参数为:" + Arrays.asList(pdj.getArgs()));

        /*执行目标方法*/
        try {
            result = pdj.proceed();
            /*返回通知方法*/
            System.out.println("1返回通知方法>目标方法名" + methodName + ",返回结果为:" + result);
        } catch (Throwable e) {
            /*异常通知方法*/
            System.out.println("1异常通知方法>目标方法名" + methodName + ",异常为:" + e);
        }
        /*后置通知*/
        System.out.println("1后置通知方法>目标方法名" + methodName);
        return result;
    }

    /**
     * 使用@AfterThrowing用来处理当切入内容部分抛出异常之后的处理逻辑
     */
    @AfterThrowing("@annotation(DS)")
    public void AfterThrowing(JoinPoint point){
        System.out.println("用来处理当切入内容部分抛出异常之后的处理逻辑");
    }

}

3.写一个测试类,加上DS注解。

import com.xx.job.demo.Test01;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AOPContrller {

    @DS("dddd")
    @GetMapping("/demo")
    public void test(String name,int age){
        System.out.println("demo");
    }
}

这样一个简单的切面测试就完成了。

三、问题

1.@Before、@After、@AfterReturning、@AfterThrowing和@Around一起使用时,@Around里面什么都不做其它几个注解不会执行的。

答:@Around环绕通知,跟其它几个注解不能。@Before、@After、@AfterReturning、@AfterThrowing不会管方法的执行,只会检测方法的执行前后。而@Around直接拦截方法,而且控制切面的方法是否执行,只有@Around里面通过ProceedingJoinPoint的方法

public Object proceed() throws Throwable;执行了切面方法,其它几个注解才会生效。

2.项目启动报错 ProceedingJoinPoint is only supported for around advice

答:ProceedingJoinPoint这个类只能在@Around里面做为参数,@Before、@After、@AfterReturning、@AfterThrowing用JoinPoint。看一下ProceedingJoinPoint源码,继承JoinPoint只有两个方法,方法作用就是执行切面方法。只有在@Around环绕通知里面才需要执行方法。

package org.aspectj.lang;

import org.aspectj.runtime.internal.AroundClosure;

/**
 * ProceedingJoinPoint exposes the proceed(..) method in order to support around advice in @AJ aspects
 *
 * @author Alexandre Vasseur
 */
public interface ProceedingJoinPoint extends JoinPoint {


    /**
     * Proceed with the next advice or target method invocation
     *
     * @return the result of proceeding
     * @throws Throwable if the invoked proceed throws anything
     */
    public Object proceed() throws Throwable;

    /**
     * @param args the arguments to proceed with
     * @return the result of proceeding
     * @throws Throwable if the invoked proceed throws anything
     */
    public Object proceed(Object[] args) throws Throwable;

}

四、JoinPoint提供的API

1.Signature getSignature();获取连接点的方法签名对象;也就是切面方法的信息

2.Object[] getArgs();获取连接点方法运行时的入参列表;   切面方法的参数

3.String getKind(); 返回一个表示连接点类型的字符串。

五、ProceedingJoinPoint提供的API

1.public Object proceed() throws Throwable;执行切面方法

2.public Object proceed(Object[] args) throws Throwable;带参数执行切面方法

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值