SpringBoot自定义注解AOP面向切面编程

AOP名词基础概念

  1. 切面(Aspect)
    AOP思想就是面向切面编程,对一个我们已经封装好的类,我们可以在运行的各个时期,对其进行切割,在原有的方法中织入一些新的代码,不改变原有方法的功能,只做增强,而那些增强部分的代码,就被称为切面。常常用于权限认证,日志,事务处理等。
  2. 切入点(PointCut)
    所谓切入点,就是那个类中的那个方法进行增强,进行切割,指被增强的方法,就是要切的东西。
  3. 连接点(JoinPoint)
    在我们知道要切入那些方法之后,就需要知道在什么时候切入,比如在方法被调用之前,调用之后,发生异常等时候调用。
  4. 通知(advice)
    所谓的通知,就是通知被织入的方法,应该如何增强。
    其中@Pointcut注解为指明切入点,@Before,@After是连接点,注解对应下面的就是对应的通知。
  5. 目标对象(Target Object)
    被一个或者多个切面通知的对象,就是目标对象。
  6. 织入(Weaving)
    所谓织入,就是将切面切入到目标方法中,使得目标方法被增强的过程。

常用注解解释

@Aspect:   作用是把当前类标识为一个切面供容器读取

@Pointcut: 是声明切入点,Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码。
@Around:环绕增强,相当于MethodInterceptor
@AfterReturning:后置增强,方法执行之后再执行,相当于AfterReturningAdvice,方法正常退出时执行
@Before:前置增强方法,方法执行之前执行,相当于BeforeAdvice的功能,相似功能的还有
@AfterThrowing:异常抛出增强,相当于ThrowsAdvice
@After: 最终通知(在目标方法执行后调用,无论目标方法是否出现异常,都会执行),不管是抛出异常或者正常退出都会执行

使用方法

1:引入相关依赖

 <dependency>
     <groupId>org.springframework.bootgroupId>
     <artifactId>spring-boot-starter-aopartifactId>
 dependency>

2:自定义通知注解(本次用一个运行前注解样例)

@Target({ElementType.METHOD})//作用在方法上
@Retention(RetentionPolicy.RUNTIME)//运行时
public @interface Refresh {
    int type() default 1;
}

切面代码

@Aspect
@Component
public class RefreshAspect {

    /**
     * 环绕通知
     * Pointcut:切入点
     */
    @Pointcut("@annotation(com.xxy.gps.annotation.Refresh)")
    private void around() {
    }

    @Around("around()")
    private Object testAop(ProceedingJoinPoint point) throws Throwable {
        System.out.println("======AopAspectJ执行环绕通知开始=========");
        Object obj = point.proceed();
        Object[] args = point.getArgs();
        //方法名
        String methodName = point.getSignature().getName();
        //对象
        Object target = point.getTarget();
        //类名
        String className = target.getClass().getName();
        System.out.println("类:" + className + ";方法:" + methodName + ";参数:" + JSONArray.toJSONString(args));
        System.out.println("======AopAspectJ执行环绕通知结束=========");
        return obj;
    }

    /**
     * 前置通知
     */
    @Before("@annotation(refresh)")
    public void beforeAdvance(Refresh refresh) {
        System.out.println("======AopAspectJ执行前置通知=========");
    }

    /**
     * 后置通知(在目标方法执行后调用,若目标方法出现异常,则不执行)
     */
    @AfterReturning("@annotation(refresh)")
    private void afterRunningAdvance(Refresh refresh) {
        System.out.println("type=" + refresh.type());
        System.out.println("======AopAspectJ执行后置通知=========");
    }

    /**
     * 最终通知(在目标方法执行后调用,无论目标方法是否出现异常,都会执行)
     */
    @Pointcut("@annotation(com.xxy.gps.annotation.Refresh)")
    private void after() {
    }

    @After("after()")
    public void afterAdvance() {
        System.out.println("======AopAspectJ执行最终通知=========");
    }

    /**
     * 异常通知:目标方法抛出异常时执行
     */
    @AfterThrowing("@annotation(refresh)")
    public void afterThrowingAdvance(Refresh refresh) {
        System.out.println("======AopAspectJ执行异常通知=========");
    }
}

测试

@Component
public class MyTest {
    @Refresh
    public void log() {
        System.err.println("输出日志");
    }
}
@SpringBootTest
class GpsServiceApplicationTests {
    @Autowired
    private MyTest myTest;
    @Test
    void contextLoads() {
        myTest.log();
    }
}

你可能感兴趣的:(spring,boot,java,spring)