通过spring的AOP的切面,拦截到持久层执行的sql及参数

声明:文章内容是 自己使用后整理,大部分工具代码出自大牛,但因无法确认出处,故仅在此处由衷的对无私分享源代码的作者表示感谢与致敬!

使用该方式需要按规范书写所有的mapper方法,否则会报错

方式一:形参为自定义实体类
void insert(User user);

方式二:形参为Map
void insert(Map<String,Object> map);

方式三:形参为list

void batchInsertUser(@Param(value = "list") List<UserDTO> list);

方式四:形参为单个或多个参数,需要使用@Param注解
void insert(@Param("userName") String userName, @Param("age")Integer age);

LogSqlAnnotation.java

package com.xxx.xxx.xxx.aspect;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
 
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface LogSqlAnnotation{
   
    String value() default "";
}

LogSqlAspect.java

package com.xxx.xxx.xxx.aspect;

import com.xxx.xxx.xxx.util.Func;
import com.xxx.xxx.xxx.util.SqlUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@Slf4j
//@Aspect
//@Component
public class LogSqlAspect {


    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    /**
     * 切点 扫描整个mapper
     *
     * @Pointcut("execution(* com.xxx.xxx.xxx.controller.*.*(..)) && @annotation(com.xxx.xxx.xxx.aspect.LogSqlAnnotation)")
     * @Pointcut("execution(* com.xxx.xxx.xxx.mappers.*.*(..))")
     */
    @Pointcut("execution(* com.xxx.xxx.xxx.mapper.*.*(..)) && !execution(* com.xxx.xxx.xxx.mapper.JobLogSqlMapper.*(..))")
    public void logRecord() {
        // 定义
    }

    /**
     * 前置通知
     *
     * @param jp
     */
    @Before(value = "logRecord()")
    public void before(JoinPoint jp) {
        String name = jp.getSignature().getName();
        log.info(name + "方法开始执行");
    }

    /**
     * 后置通知
     *
     * @param jp
     */
    @After(value = "logRecord()")
    public void after(JoinPoint jp) {
        String name = jp.getSignature().getName();
        log.info(name + "方法执行结束...");
    }

    /**
     * 返回通知
     *
     * @param jp
     * @param result
     */
    @AfterReturning(value = "logRecord()", returning = "result")
    public void afterReturning(JoinPoint jp, Object result) {
        String name = jp.getSignature().getName();
        log.info(name + "方法返回值为:" + result);
    }

    /**
     * 异常通知
     *
     * @param jp
     * @param e
     */
    @AfterThrowing(value = "logRecord()", throwing = "e")
    public void afterThrowing(JoinPoint jp, Exception e) {
        String name = jp.getSignature().getName();
        log.info(name + "方法异常:" + e.getMessage());
    }

    //    @Around(value = "logRecord()")
//    public Object around(ProceedingJoinPoint pjp) throws Throwable {
//        return pjp.proceed();
//    }


    @Around(value = "logRecord()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {

        String sql = SqlUtils.getMybatisSql(pjp, sqlSessionFactory);
        String dml= Func.getSqlDML(sql);
        String remark= Func.analyzeSqlWhere(sql);

        // 获取请求信息
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        String requestUrl=null;
        if(requestAttributes!=null){
            HttpServletRequest request = requestAttributes.getRequest();
            requestUrl = request.getRequestURL().toString();
        }
        Signature signature = pjp.getSignature();
        String methodName = signature.getName();
        String methodUrl = signature.toShortString();

        log.info("记录执行sql--->dml:{}",dml);
        log.info("记录执行sql--->remark:{}",remark);
        if(remark!=null || (remark==null && dml != null && !"SELECT".equals(dml) )){
            log.info("记录执行sql--->sql:{}",sql);
            log.info("记录执行sql--->methodName:{}",methodName);
            log.info("记录执行sql--->methodUrl:{}",methodUrl);
            log.info("记录执行sql--->requestUrl:{}",requestUrl);
        }
        /*//<editor-fold desc="1、jdbc 保存日志">
        Connection connection = JdbcUtils.getConnection();
        Statement statement = connection.createStatement();
        String insertSql = "insert into logsql(log_id, sql_str, method_name, method_url, request_url, create_date) " +
                "values (" + "\'" + logId + "\'" + ","
                + "\"" + sql + "\"" + ","
                + "\"" + methodName + "\"" + ","
                + "\'" + methodUrl + "\'" + ","
                + "\'" + requestUrl + "\'" + ","
                + "NOW()" + ")";
        statement.executeUpdate(insertSql);
        //</editor-fold>*/

        /*//<editor-fold desc="2、mybatis 通过model方式保存">
        LogSql logSql = new LogSql();
        logSql.setLogId(logId);
        logSql.setMethodName(methodName);
        logSql.setMethodUrl(methodUrl);
        logSql.setSqlStr(sql);
        logSql.setRequestUrl(requestUrl);
        logSqlMapper.saveLogByModel(logSql);
        //</editor-fold>*/

        // 3、mybatis 通过 map方式保存"
//        Map<String, String> map = new HashMap<>(16);
//        map.put("sql_str", sql);
//        map.put("method_name", methodName);
//        map.put("method_url", methodUrl);
//        map.put("request_url", requestUrl);
//    logSqlMapper.saveLogByMap(map);

        return pjp.proceed();
    }

}

SqlUtils.java

package com.xxx.xxx.xxx.util;

import com.google.common.collect.Lists;
import com.xxx.xxx.xxx.model.log.LogSqlConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.text.DateFormat;
import java.time.Instant;
import java.util.*;


/**
 * @date 2021/9/20 10:16
 * @description  获取aop中的SQL语句,借鉴来源https://blog.csdn.net/sdzhangshulong/article/details/104393244
 */
@Slf4j
public class SqlUtils {

    /**
     * 获取aop中的SQL语句
     *
     * @param pjp
     * @param sqlSessionFactory
     * @return
     * @throws IllegalAccessException
     */
    public static String getMybatisSql(ProceedingJoinPoint pjp, SqlSessionFactory sqlSessionFactory) throws IllegalAccessException {
        Map<String, Object> map = new HashMap<>(16);
        //1.获取namespace+methdoName
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        String namespace = method.getDeclaringClass().getName();
        String methodName = method.getName();
        //2.根据namespace+methdoName获取相对应的MappedStatement
        Configuration configuration = sqlSessionFactory.getConfiguration();
        MappedStatement mappedStatement = configuration.getMappedStatement(namespace + "." + methodName);
        //3.获取方法参数列表名
        Parameter[] parameters = method.getParameters();
        //4.形参和实参的映射,获取实参
        Object[] objects = pjp.getArgs();
        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
        for (int i = 0; i < parameterAnnotations.length; i++) {
            Object object = objects[i];
            //说明该参数没有注解,此时该参数可能是实体类,也可能是Map,也可能只是单参数
            if (parameterAnnotations[i].length == 0) {
                if (object.getClass().getClassLoader() == null && object instanceof Map) {
                    map.putAll((Map<? extends String, ?>) object);
                    log.info("该对象为Map");
                } else {//形参为自定义实体类
                    map.putAll(objectToMap(object));
                    log.info("该对象为用户自定义的对象");
                }
            } else {//说明该参数有注解,且必须为@Param
                for (Annotation annotation : parameterAnnotations[i]) {
                    if (annotation instanceof Param) {
                        map.put(((Param) annotation).value(), object);
                    }
                }
            }
        }
        //5.获取boundSql
        BoundSql boundSql = mappedStatement.getBoundSql(map);
//        BoundSql boundSql = mappedStatement.getBoundSql();
        return showSql(configuration, boundSql);
    }

    /**
     * 解析BoundSql,生成不含占位符的SQL语句
     *
     * @param configuration
     * @param boundSql
     * @return
     */
    private static String showSql(Configuration configuration, BoundSql boundSql) {
        Object parameterObject = boundSql.getParameterObject();
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
        if (parameterMappings.size() > 0 && parameterObject != null) {
            TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
            if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
                sql = sql.replaceFirst("\\?", getParameterValue(parameterObject));
            } else {
                MetaObject metaObject = configuration.newMetaObject(parameterObject);
                for (ParameterMapping parameterMapping : parameterMappings) {
                    String propertyName = parameterMapping.getProperty();
                    String[] s = metaObject.getObjectWrapper().getGetterNames();
                    s.toString();
                    if (metaObject.hasGetter(propertyName)) {
                        Object obj = metaObject.getValue(propertyName);
                        sql = sql.replaceFirst("\\?", getParameterValue(obj));
                    } else if (boundSql.hasAdditionalParameter(propertyName)) {
                        Object obj = boundSql.getAdditionalParameter(propertyName);
                        sql = sql.replaceFirst("\\?", getParameterValue(obj));
                    }
                }
            }
        }
        return sql;
    }

    /**
     * 若为字符串或者日期类型,则在参数两边添加''
     *
     * @param obj
     * @return
     */
    private static String getParameterValue(Object obj) {
        String value = null;
        if (obj instanceof String) {
            value = "'" + obj.toString() + "'";
        } else if (obj instanceof Date) {
            DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);
            value = "'" + formatter.format(new Date()) + "'";
        } else {
            if (obj != null) {
                value = obj.toString();
            } else {
                value = "";
            }
        }
        return value;
    }

    /**
     * 获取利用反射获取类里面的值和名称
     *
     * @param obj
     * @return
     * @throws IllegalAccessException
     */
    private static Map<String, Object> objectToMap(Object obj) throws IllegalAccessException {
        Map<String, Object> map = new HashMap<>(16);
        Class<?> clazz = obj.getClass();
        log.info("Class<?>={}",clazz);
        // 获取本类及其父类的属性,↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        // 获取本类及其父类的属性,↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
        for (Field field : fieldList) {
            field.setAccessible(true);
            String fieldName = field.getName();
            Object value = field.get(obj);
            map.put(fieldName, value);
        }
        return map;
    }

    /**
     * 获取 DML 的 方式(insert、delete、update、select)
     * @param sql
     * @return
     */
    public static String getSqlDML(String sql) {

        if(Func.isEmpty(sql)){
            return null;
        }
        try {
            sql=sql.trim();
            int endIndex = sql.indexOf(" ")!=-1?sql.indexOf(" "):sql.length()>=6?6:sql.length();
            return sql.substring(0, endIndex).toUpperCase();
        } catch (Exception e) {
            log.error("SqlUtils- 获取sql的DML 异常",e);
            return null;
        }
    }

    /**
     * 获取表名
     * @param sql
     * @return
     */
    public static String getTableName(String sql) {

        String dml = getSqlDML(sql);

        if(Func.isEmpty(dml)){
            return null;
        }
        // LogSqlEnum.DmlEnum.UPDATE.equals(dml) || LogSqlEnum.DmlEnum.DELETE.equals(dml) || LogSqlEnum.DmlEnum.SELECT.equals(dml)
        try {
            sql = sql.substring(6).trim().toUpperCase();
            if((LogSqlConstant.DmlEnum.DELETE.equals(dml) || LogSqlConstant.DmlEnum.SELECT.equals(dml))
                    && sql.contains("FROM")){
                sql=sql.substring(sql.indexOf("FROM")+4).trim();
                String[] s = sql.split(" ");
                if(s.length>1){
                    return s[0].trim();
                }
            }
            if(LogSqlConstant.DmlEnum.UPDATE.equals(dml) && sql.contains("SET")){
                return sql.substring(6,sql.indexOf("SET")).trim();
            }
            return null;
        } catch (Exception e) {
            log.error("SqlUtils- 获取表名 异常",e);
            return null;
        }
    }

    /**
     * 分析sql的where条件
     * @param sql
     * @return
     */
    public static String analyzeSqlWhere(String sql) {
        try {
            String dml = getSqlDML(sql);
            // 忽略枚举表
            if(LogSqlConstant.DmlEnum.SELECT.equals(dml)
                    && LogSqlConstant.getIgnoreTable().contains(getTableName(sql))){
                return null;
            }

            if(LogSqlConstant.DmlEnum.UPDATE.equals(dml) || LogSqlConstant.DmlEnum.DELETE.equals(dml) || LogSqlConstant.DmlEnum.SELECT.equals(dml)){
                String sqlUpperCase = sql.toUpperCase();

                if(!sqlUpperCase.contains("WHERE")){
                    return "【高风险sql】"+dml+"无WHERE条件";
                }else {
                    String whereStr = sqlUpperCase.substring(sqlUpperCase.indexOf("WHERE")+5);
                    if(whereStr.contains("GROUP BY")){
                        whereStr = whereStr.substring(0,whereStr.indexOf("GROUP BY"));
                    }else if(whereStr.contains("ORDER BY")){
                        whereStr = whereStr.substring(0,whereStr.indexOf("ORDER BY"));
                    }
                    whereStr = whereStr.trim();
                    List<String> blList = Lists.newArrayList();
                    if(whereStr.contains("(")){
                        String[] bl = whereStr.split("\\(");
                        for (String b : bl) {
                            if(Func.isNotEmpty(b)){
                                blList.add(b);
                            }
                        }
                    }
                    List<String> brList = Lists.newArrayList();
                    for (String bl : blList) {
                        String[] br = bl.split("\\)");
                        for (String b : br) {
                            if(Func.isNotEmpty(b)){
                                brList.add(b);
                            }
                        }
                    }
                    List<String> andList = Lists.newArrayList();
                    for (String br : brList) {

                        String[] ands = br.split("AND");
                        for (String s : ands) {
                            if(Func.isNotEmpty(s)){
                                andList.add(s);
                            }
                        }
                    }

                    List<String> orList = Lists.newArrayList();
                    for (String an : andList) {
                        String[] ors = an.split("OR");
                        for (String s : ors) {
                            if(Func.isNotEmpty(s)){
                                orList.add(s);
                            }
                        }
                    }
                    StringBuilder nullSB = new StringBuilder();
                    for (String or : orList) {
                        String[] eqs = or.split("=");
                        if(eqs.length==2
                                && (Func.isEmpty(eqs[1]) || "null".equalsIgnoreCase(eqs[1].trim()) )){
                            nullSB.append(or).append(";");
                        }
                    }

                    return nullSB.length()>0?nullSB.insert(0,"【中风险sql】条件值为空:").toString():null;
                }
            }
            return null;
        } catch (Exception e) {
            log.error("SqlUtils-分析sql的where条件异常",e);
            return "SqlUtils-分析sql的where条件异常";
        }
    }


    public static void main(String[] args) {
//        System.out.println(getSqlDML("insertaass"));

        String sql0="select * from t_test where (sex='男' or sex='女' or id in (1) ) and name=null and id=2 and age in (1,2,3) group by dept order by id desc";
        String sql2="select day as day, code as code from t_day where day >= '2021-09-08' and day <= '2021-09-08' and (code = '0' or code = '2')";
        
//        String analyzeSqlWhere = analyzeSqlWhere(sql);
//        System.out.println(analyzeSqlWhere);

    }

}
LogSqlConstant.java
package com.xxx.xxx.xxx.model.log;

import com.google.common.collect.Sets;

import java.util.Set;

public class LogSqlConstant {

    public enum DmlEnum {
        SELECT,INSERT,UPDATE,DELETE;
    }

    public static Set<String> getIgnoreTable(){
        return Sets.newHashSet("T_PRIORITY","T_STATUS_TYPE","T_B_TYPE","T_A_TYPE");
    }
}

Func.java

package com.xxx.xxx.xxx.util;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * 高频方法集合类
 */
public class Func {

    /**
     * 两个字符串数值 乘法
     *
     * @return
     */
    public static String multiply(String arg1, String arg2) {
        BigDecimal bg1 = new BigDecimal(arg1);
        BigDecimal bg2 = new BigDecimal(arg2);
        return bg1.multiply(bg2).toString();
    }

    /**
     * 比较两个对象是否相等。<br>
     * 相同的条件有两个,满足其一即可:<br>
     * 1. obj1 == null && obj2 == null; 2. obj1.equals(obj2)
     *
     * @param obj1 对象1
     * @param obj2 对象2
     * @return 是否相等
     */
    public static boolean equals(Object obj1, Object obj2) {
        return (obj1 != null) ? (obj1.equals(obj2)) : (obj2 == null);
    }

    /**
     * 计算对象长度,如果是字符串调用其length函数,集合类调用其size函数,数组调用其length属性,其他可遍历对象遍历计算长度
     *
     * @param obj 被计算长度的对象
     * @return 长度
     */
//    public static int length(Object obj) {
//        return ObjectKit.length(obj);
//    }

    /**
     * 对象中是否包含元素
     *
     * @param obj     对象
     * @return 是否包含
     */
//    public static boolean contains(Object obj, Object element) {
//        return ObjectKit.contains(obj, element);
//    }

    public static boolean isNotEmpty(Object obj) {
        return !isEmpty(obj);
    }

    /**
     * 对象是否为空
     *
     * @param obj String,List,Map,Object[],int[],long[]
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static boolean isEmpty(Object obj) {
        if (obj == null) {
            return true;
        }
        if (obj instanceof String) {
            if (obj.toString().trim().equals("")) {
                return true;
            }
        } else if (obj instanceof List) {
            if (((List) obj).size() == 0) {
                return true;
            }
        } else if (obj instanceof Map) {
            if (((Map) obj).size() == 0) {
                return true;
            }
        } else if (obj instanceof Set) {
            if (((Set) obj).size() == 0) {
                return true;
            }
        } else if (obj instanceof Object[]) {
            if (((Object[]) obj).length == 0) {
                return true;
            }
        } else if (obj instanceof int[]) {
            if (((int[]) obj).length == 0) {
                return true;
            }
        } else if (obj instanceof long[]) {
            if (((long[]) obj).length == 0) {
                return true;
            }
        }
        return false;
    }

    /**
     * 对象组中是否存在 Empty Object
     *
     * @param os 对象组
     * @return
     */
    public static boolean isOneEmpty(Object... os) {
        for (Object o : os) {
            if (isEmpty(o)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 对象组中是否全是 Empty Object
     *
     * @param os
     * @return
     */
    public static boolean isAllEmpty(Object... os) {
        for (Object o : os) {
            if (!isEmpty(o)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 是否为数字
     *
     * @param obj
     * @return
     */
    public static boolean isNum(Object obj) {
        try {
            Integer.parseInt(obj.toString());
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 数字是否为Null或Zero
     *
     * @param obj
     * @return
     */
    public static boolean isNullOrZero(Object obj) {
        if (obj == null) {
            return true;
        }

        if (obj instanceof Integer) {
            try {
                return Integer.parseInt(obj.toString()) == 0;
            } catch (Exception e) {
                return false;
            }
        }

        if (obj instanceof Long) {
            try {
                return Long.parseLong(obj.toString()) == 0L;
            } catch (Exception e) {
                return false;
            }
        }
        return false;
    }

    /**
     * 如果为空, 则调用默认值
     *
     * @param str
     * @return
     */
    public static Object getValue(Object str, Object defaultValue) {
        if (isEmpty(str)) {
            return defaultValue;
        }
        return str;
    }

    /**
     * map的key转为小写
     *
     * @param map
     * @return Map<String   ,   Object>
     */
    public static Map<String, Object> caseInsensitiveMap(Map<String, Object> map) {
        Map<String, Object> tempMap = new HashMap<>();
        for (String key : map.keySet()) {
            tempMap.put(key.toLowerCase(), map.get(key));
        }
        return tempMap;
    }

    /**
     * 获取map中第一个数据值
     *
     * @param <K> Key的类型
     * @param <V> Value的类型
     * @param map 数据源
     * @return 返回的值
     */
    public static <K, V> V getFirstOrNull(Map<K, V> map) {
        V obj = null;
        for (Entry<K, V> entry : map.entrySet()) {
            obj = entry.getValue();
            if (obj != null) {
                break;
            }
        }
        return obj;
    }

    /**
     * 创建StringBuilder对象
     *
     * @return StringBuilder对象
     */
    public static StringBuilder builder(String... strs) {
        final StringBuilder sb = new StringBuilder();
        for (String str : strs) {
            sb.append(str);
        }
        return sb;
    }

    /**
     * 创建StringBuilder对象
     *
     * @return StringBuilder对象
     */
    public static void builder(StringBuilder sb, String... strs) {
        for (String str : strs) {
            sb.append(str);
        }
    }


    /**
     *  清除两边的空格
     * @param sql " aa bb cc "
     * @return "aa bb cc"
     */
    public static String clearSideSpaces(String sql) {
        if(Func.isEmpty(sql)){
            return "";
        }
        return sql.trim();
    }
    /**
     *  清除中间的空格
     * @param sql " aa bb
                    cc "

     * @return " aa bb cc "
     */
    public static String clearMiddleSpaces(String sql) {
        if(Func.isEmpty(sql)){
            return "";
        }
        return sql.replaceAll("[\\s]+", " ");
    }
    /**
     *  清除(两边+中间)的空格
     * @param sql " aa bb
                    cc "

     * @return "aa bb cc"
     */
    public static String clearExtraSpaces(String sql) {
        if(Func.isEmpty(sql)){
            return "";
        }
        return sql.replaceAll("[\\s]+", " ").trim();
    }

    public static void main(String[] args) {
        String sql = " aa bb cc ";
        System.out.println("--"+clearMiddleSpaces(sql)+"--");
    }
}

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Spring AOP(Aspect-Oriented Programming)是Spring框架提供的一种面向切面编程的现方式。它允许开发人员将横切关注点(如日志记录、事务管理等)与核心业务逻辑进行分离,从而提高代码的可重用性和可维护性。 在Spring AOP中,通过定义切面(Aspect)来描述横切关注点,然后将切面与目标对象进行关联。切面可以通过配置文件或注解的方式进行声明。在运行时,Spring AOP会根据定义的切面规则自动将切面逻辑织入到目标对象的方法中。 切面由切点(Pointcut)和通知(Advice)组成。切点定义了在哪些方法上应用切面逻辑,通知定义了切面逻辑的具体实现。通知可以在目标方法执行前、执行后、抛出异常时等不同的时机触发。 常见的通知类型包括: - 前置通知(Before Advice):在目标方法执行执行; - 后置通知(After Advice):在目标方法执行执行,无论是否发生异常; - 返回通知(After Returning Advice):在目标方法执行执行,仅在目标方法成功返回时触发; - 异常通知(After Throwing Advice):在目标方法抛出异常后执行; - 环绕通知(Around Advice):在目标方法执行前后都执行,可以控制目标方法的执行流程。 Spring AOP可以应用于各个层面,如业务逻辑、数据访问、事务管理等,通过将横切关注点与核心业务逻辑解耦,可以提高代码的模块化和可维护性。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值