简单的例子来理解Spring Aop的基本概念

        一个常见的应用场景是,当我们需要在程序执行某个方法前后,进行日志记录、权限检查或者其他额外的处理操作时。这时候,我们可以使用AOP编程来实现。

      

一、XML配置AOP

        举个例子,假设我们有一个名为`UserService`的服务类,其中包含了创建用户和更新用户信息的方法。为了在每次执行这两个方法时,都先记录一份执行日志,我们可以通过AOP来实现:  

        1. 创建一个切面类`LogAspect`,该类需要实现`MethodInterceptor`接口。

public class LogAspect implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        // 记录开始时间
        long startTime = System.currentTimeMillis();
        // 执行目标方法
        Object result = invocation.proceed();
        // 计算方法执行时间,并打印日志
        long endTime = System.currentTimeMillis();
        System.out.println("方法[" + invocation.getMethod().getName() + "]执行耗时" + (endTime - startTime) + "毫秒");
        return result;
    }
}

        2. 在Spring配置文件中,将`LogAspect`类声明为一个切面,并指定要拦截的方法。

<bean id="logAspect" class="com.example.aspect.LogAspect"/>
<aop:config>
    <aop:aspect ref="logAspect">
        <aop:pointcut id="userServicePointCut" expression="execution(* com.example.service.UserService.*(..))" />
        <aop:around pointcut-ref="userServicePointCut" method="invoke" />
    </aop:aspect>
</aop:config>

【xml配置分析:这段代码是Spring AOP的配置,用于将自定义的切面类`LogAspect`应用到`UserService`服务类中的方法上。

        (1)第一行定义一个ID为`logAspect`的Bean,类型为`com.example.aspect.LogAspect`,即定义了一个切面。
        (2)在`aop:config`标签内声明了一个aspect(切面),引用了声明好的`logAspect`。
        (3)`aop:pointcut`元素声明了一个名为`userServicePointCut`的切入点,该切入点表达式指定了要拦截的类和方法。其中`execution(* com.example.service.UserService.*(..))`表示要匹配`com.example.service.UserService`类下的任何方法。
        (4)`aop:around`元素则将该切面的拦截动作设置为"环绕通知",将前置、后置通知(切面操作)和目标方法合并在一个方法体中,并控制是否执行目标方法或直接返回结果,同时在合适的时候添加新的流程处理。】

        3. 重启应用程序,每次执行`UserService`中的方法时,都会在控制台上输出方法执行时间的日志记录了。

        这样,我们就通过AOP编程,实现了对方法执行时间的自动记录。另外,如果要实现权限检查等其他功能,只需要添加一个类似的切面即可。

二、注解配置AOP

        举个例子,假设你要在`com.example.service.UserService`类上增加日志打印的横切关注点,那么可以按以下步骤来实现:

        1. 定义一个日志切面类,该类使用Aspect注解标记,并在其内部定义一个pointcut切入点(具体对应到UserService的某个方法)和一个advice增强处理逻辑,如下所示:

@Component
@Aspect
public class LogAspect {
    @Pointcut("execution(* com.example.service.UserService.*(..))")
    public void servicePointCut() {
    }

    @Around("servicePointCut()")
    public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
        // 打印日志
        System.out.println("Method " + joinPoint.getSignature().getName() + " is invoked.");
        // 执行原有逻辑
        Object result = joinPoint.proceed();
        return result;
    }
}

        2. 在Spring配置文件中开启注解驱动的AOP自动代理机制,同时导入上述切面类,如下所示:

<context:component-scan base-package="com.example"/>
<aop:aspectj-autoproxy />
<bean id="logAspect" class="com.example.aspect.LogAspect"/>

        其中第一行表示启用注解扫描,并设置扫描包路径为`com.example`,第二行则表示启用AspectJ注解的AOP自动代理机制,第三行定义的是之前实现的日志切面`LogAspect`类的Bean。

        相比于XML配置方式,使用注解的方式更加简洁和灵活,能够提高开发效率,并且可以让代码更具可读性。

猜你喜欢

转载自blog.csdn.net/weixin_52060913/article/details/130529887