第十二节 SSM架构使用AOP技术记录操作日志

亮子 2023-10-16 13:16:20 20433 0 0 0

1、定义一个切面类

package com.shenmazong.zg2.aop;

import com.shenmazong.zg2.mapper.TbUserMapper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Arrays;

/**
 * @author 军哥
 * @version 1.0
 * @description: 切面类
 * @date 2023/10/16 19:46
 */

public class MyRecordLog {

    @Autowired
    TbUserMapper tbUserMapper;

    /**
     * 前置通知:数据校验,身份校验
     * @param jp 连接点参数Joinpoint,必须放在方法的第一位,可对切入点进行分析
     *           比如拿连接点的名字,连接点的所在类,连接点的参数
     */
    public void before(JoinPoint jp){
        System.out.println("1...前置通知,切入类"+jp.getTarget().getClass());
        System.out.println("1...前置通知,切入方法"+jp.getSignature().getName());
        System.out.println("1...前置通知,参数:"+ Arrays.toString(jp.getArgs()));
    }

    /**
     * 环绕通知:事务控制,权限控制,返回对象
     * @param pjp 对连接点的方法内容进行整体控制
     * @return 返回连接点的返回值
     * @throws Throwable 连接点有异常则抛出
     */
    public Object around(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("2...环绕前置, 在执行用辅助业务");
        Object obj = pjp.proceed(); //调用核心业务
        System.out.println("2...环绕返回对象:"+obj.toString());
        System.out.println("2...环绕后置, 在执行用辅助业务");
        return obj;

    }

    /**
     * 后置通知:日志记录,返回对象
     * @param jp 连接点的基本信息
     * @param result 获取连接点的返回对象
     */
    public void afterReturning(JoinPoint jp,Object result){
        System.out.println("3...后置通知,切入类"+jp.getTarget().getClass());
        System.out.println("3...后置通知,切入方法"+jp.getSignature().getName());
        System.out.println("3...后置通知,返回对象为:"+result);
    }

    /**
     * 最终通知:在方法最后执行
     * @param jp 连接点的基本信息
     */
    public void after(JoinPoint jp){
        System.out.println("4...最终通知,切入类"+jp.getTarget().getClass());
        System.out.println("4...最终通知,切入方法"+jp.getSignature().getName());
    }

    /**
     * 异常通知:异常处理,事务控制
     * 在目标方法抛出异常时执行的通知
     * @param jp 连接点的基本信息
     * @param e 连接点的异常信息
     */
    public void afterThrow(JoinPoint jp,Throwable e){
        System.out.println("5...异常通知,切入类"+jp.getTarget().getClass());
        System.out.println("5...异常通知,切入方法"+jp.getSignature().getName());
        System.out.println(e.getMessage());
    }
}

2、在springmvc.xml配置中加入如下配置

    <aop:aspectj-autoproxy proxy-target-class="true" />

由于springmvc默认使用的是动态代理,所以没有实现接口的类是无法生效的。如果想拦截controler,则需要加入上面的配置。

3、在spring.xml加入如下配置

<!--    https://blog.csdn.net/qq_42495847/article/details/105866684-->
    <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>

<!--    <bean id="tbUserService" class="com.shenmazong.zg2.service.impl.TbUserServiceImpl"/>-->
    <bean id="indexController" class="com.shenmazong.zg2.controller.IndexController"/>
    <bean id="myRecordLog" class="com.shenmazong.zg2.aop.MyRecordLog">
    </bean>
    <aop:config>
        <!-- 配置切入点 方法1 addUser-->
<!--        <aop:pointcut id="pc001" expression="execution(* com.shenmazong.zg2.service.impl.TbUserServiceImpl.*(..))" />-->
        <aop:pointcut id="pc001" expression="execution(* com.shenmazong.zg2.controller.IndexController.*(..))" />

        <!-- 配置切面 -->
        <aop:aspect ref="myRecordLog">
            <!-- 前置通知 -->
            <aop:before method="before" pointcut-ref="pc001"/>
        </aop:aspect>
    </aop:config>

这个aop:config标签可以有多个。

4、测试结果

图片alt

参考文章