@Aspect注解切面编程

我们经常说Spring两个特点,一个是IOC控制反转,这个好说你要是从之前那种需要哪个就要创建那个对象的常规基础面向对象编程走过来,基本来说你大概明白IOC这个给你省了不少事。

但是还有一个特点就是AOP,就是面向切面编程。市面常见的资料一举例子就是日志,关键是真正项目我们都会引入日志包,根本不需要你去设置什么切面。所以对于面向切面编程,到底是个啥,估计有的人还是有点懵。

一 先聊聊Aspect和SpringAOP
会发现@Aspect不再Spring的包里面,实际上Aspect和SpringAOP实际上算是AOP的两套方案,Aspect是解决编程中的AOP问题,SpringAOP是让Spring的AOP更方便,更专注在Spring中的应用。

但是我们在日常工程中经常搭配而这一起用,类似下面:一般是@Aspect是生命这是一个切面类,@component是是把他交给Spring容器来管理。

@Aspect
@Component
public class ViewSyncSupport {
    //do  something
}

二 AOP的一些术语
做了个切面,不是结束,还要很多细节和属于要理解,来搭配你的实际业务的使用。

Advice (通知,切面要完成的工作)
Joinpoint (连接点,执行过程插入切面的点)
Pointcut (切点,切面在何处执行)
Weaving (织入,把切面应用到目标对象并创建新的代理对象的过程)

对应这些也会有注解来帮助处理AOP:

@Pointcut
定义一个切点,有两种表达方式

 @Pointcut("@annotation(com.lxzl.ams.dynamicform.annotation.DynamicMethod)")

匹配所用注解对应的方法,这里就是匹配@DynamicMethod注释的方法。

 @Pointcut("execution(* com.lxzl.ams.service.excel.export.temp.ExcelIExporter.*(..))")

这个就是匹配对应的位置下的所有方法作为切点,这里就是ExcelIExporter这个类的所有方法。类似的匹配方法:

(1)execution(* *(..)):匹配所有方法。*表示任意返回值,*表示任意方法名,(..)表示任意参数。
(2)execution(public * *(..)):匹配所有public方法。
(3)execution(* com.example.service.*(..)):匹配com.example.service包下的所有方法。
(4)execution(* com.example.service..*.*(..)):匹配com.example.service包及其子包下的所有方法。
(5)execution(* com.example.service.MyService.*(..)):匹配com.example.service.MyService类中的所有方法。
(6)execution(* com.example.service.MyService.get*(..)):匹配com.example.service.MyService类中所有以get开头的方法。

围绕切点的注解,这对切点的方法的处理,可以增强这个切点方法,可以在这个切点方法被调用前执行,调用后执行,针对切点方法的返回值增强处理,以及对切点方法抛出异常的执行。

@Around:增强处理,用于指定advice的类型,是Around、Before、After、AfterReturning这四种类型中能力最强的一种

@Before:用于指定advice的类型,表示该advice在切点方法之前执行

@After:用于指定advice的类型,表示该advice在切点方法之后执行

@AfterReturning:用于指定advice的类型,功能与@After类似,不同点是可以捕获切点方法的返回值并进行增强处理(具体咋回事也没弄懂)

@AfterThrowing:当切点方法抛出异常时会执行该advice

三 结合代码切点和连接点
切面上有其切点,这个很好理解,你声明这个类是切面类(@Aspect),在这个切面上的点(@Pointcut)。

连接点,指程序执行过程中的某个特定点,比如方法的调用、异常的抛出等。

// 引入相关的包
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

// 使用@Aspect注解声明一个切面
@Aspect
@Component
public class LoggingAspect {

    // 使用@Pointcut注解定义一个切点,匹配com.example.service包及其子包下的所有方法
    @Pointcut("execution(* com.example.service..*.*(..))")
    public void loggingPointcut() {
        // 这个方法的内容不重要,只是作为切点表达式的一个占位符
    }

    // 使用@Before注解定义一个前置通知,引用刚刚定义的切点
    @Before("loggingPointcut()")
    public void logBefore(JoinPoint joinPoint) {
        // 在这里,joinPoint代表一个连接点,即目标方法
        System.out.println("Before method: " + joinPoint.getSignature().getName());
    }
}

在这个示例中,我们定义了一个名为loggingPointcut的切点,用于匹配com.example.service包及其子包下的所有方法。这些方法就是连接点,即我们需要在其上执行通知的目标方法。

接着,我们定义了一个前置通知(@Before),并引用刚刚定义的切点。在logBefore方法中,我们使用JoinPoint参数获取到当前连接点的信息,比如方法名等。这样,在目标方法执行之前,我们可以打印相应的日志信息。

总之,在Spring AOP中,连接点表示目标方法,而切点表示需要应用通知的目标方法的集合。通过定义切点和通知,我们可以在不修改原有代码的情况下,为目标方法添加额外的功能。这提高了代码的可扩展性和可维护性。

你可能感兴趣的:(java,开发语言)