SpringBoot 使用@Aspect进行日志管理(基于反射代理模式+动态修改注解Log)

在上一篇“SpringBoot 使用@Aspect进行日志管理(基于反射代理模式+注解Log)”的基础上,添加注解进行日志管理升级版
1、修改日志注解类

/**
 * 日志注解
 * Created by 陈梓平 on 2017/9/7.
 */
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface JournalLog {
    /** 要执行的操作类型比如:add **/
     int operationType() default -1;
    /** 要执行的模块名称如:Carouse **/
     int modularTypeName() default -1;
     /**注解说明*/
     String xplain() default "";
     /**判断类型*/
     boolean checkBoolean() default false;
    /**注解说明数组*/
    String[] xplainArray() default "";

}

2、添加注解工具类

/**
 * 注解工具类
 * Created by 陈梓平 on 2017/9/11.
 */
public class AnnotationUtils {
    /**日志输出*/
    private static final Logger logger = LoggerFactory.getLogger(AnnotationUtils.class);

    private static AnnotationUtils mInstance;

    public AnnotationUtils() {
    }

    public static AnnotationUtils get() {
        if (mInstance == null) {
            synchronized (AnnotationUtils.class) {
                if (mInstance == null) {
                    mInstance = new AnnotationUtils();
                }
            }
        }
        return mInstance;
    }

    /**
     * 获取注解属性值信息
     * @param className 类名
     * @param methodName 方法名
     * @param annotationClass 注解类
     * @param attrName 注解属性名
     * @throws NotFoundException
     */
    public static Object getAnnotationAttr(String className,String methodName,Class<?> annotationClass,String attrName) throws NotFoundException, NoSuchMethodException {

        Object value = null;
        if (StringUtils.isBlank(className))
            return value;
        if (StringUtils.isBlank(methodName))
            return value;
        if (annotationClass==null)
            return value;
        if (StringUtils.isBlank(attrName))
            return value;

        ClassPool pool = ClassPool.getDefault();
        //获取要修改的类的所有信息
        CtClass ct = pool.get(className);
        CtMethod ctMethod = ct.getDeclaredMethod(methodName);
        MethodInfo methodInfo = ctMethod.getMethodInfo();
        //获取注解属性
        AnnotationsAttribute attribute = (AnnotationsAttribute) methodInfo.getAttribute(AnnotationsAttribute.visibleTag);

        String annotationName = annotationClass.getName();
        Method operationType = annotationClass.getDeclaredMethod(attrName);
        Class<?> returnType = operationType.getReturnType();

        if (attribute!=null){
            //获取注解
            Annotation annotation = attribute.getAnnotation(annotationName);
            if (annotation!=null){
                //获取注解的值
                if (int.class.isAssignableFrom(returnType)){
                    IntegerMemberValue memberValue = (IntegerMemberValue) annotation.getMemberValue(attrName);
                    if (memberValue!=null)
                        value =  memberValue.getValue() ;
                }
                if (String.class.isAssignableFrom(returnType)){
                    StringMemberValue memberValue = (StringMemberValue) annotation.getMemberValue(attrName);
                    if (memberValue!=null)
                        value = memberValue .getValue() ;
                }
                if (boolean.class.isAssignableFrom(returnType)){
                    BooleanMemberValue memberValue = (BooleanMemberValue) annotation.getMemberValue(attrName);
                    if (memberValue!=null)
                         value = memberValue.getValue() ;
                }
                if (String[].class.isAssignableFrom(returnType)){
                    ArrayMemberValue memberValue = (ArrayMemberValue) annotation.getMemberValue(attrName);
                    if (memberValue!=null){
                        MemberValue[] strValueArray = memberValue.getValue();
                        String[] strValueA = new String[strValueArray.length];
                        for (int i = 0;i<strValueArray.length;i++){
                            StringMemberValue  stringMemberValue = (StringMemberValue) strValueArray[i];
                            strValueA[i] = stringMemberValue.getValue();
                        }
                        value = strValueA;
                    }
                }
            }
        }
        return value;
    }

    /**
     * 修改注解属性
     * @param className 类名
     * @param methodName 方法名
     * @param annotationClass 注解名
     * @param attrName 属性名
     * @param value 修改值
     * @throws NotFoundException
     */
    public static boolean updateAnnotationAttr(String className,String methodName,Class<?> annotationClass,String attrName,Object value) throws NotFoundException, NoSuchMethodException {
        if (StringUtils.isBlank(className))
            return false;
        if (StringUtils.isBlank(methodName))
            return false;
        if (annotationClass==null)
            return false;
        if (StringUtils.isBlank(attrName))
            return false;
        if (value==null)
            return false;
        ClassPool pool = ClassPool.getDefault();
        //获取需要修改的类
        CtClass ct = pool.get(className);
        CtMethod minInfo = ct.getDeclaredMethod(methodName);
        MethodInfo methodInfo = minInfo.getMethodInfo();

        ConstPool cp = methodInfo.getConstPool();
        AnnotationsAttribute attribute = new AnnotationsAttribute(cp, AnnotationsAttribute.visibleTag);

        String annotationName = annotationClass.getName();
        Method operationType = annotationClass.getDeclaredMethod(attrName);
        Class<?> returnType = operationType.getReturnType();
        Annotation annotation = new Annotation(annotationName, cp);
        //修改名称为unitName的注解
        if (annotation != null) {

            if (String.class.isAssignableFrom(returnType))
                annotation.addMemberValue(attrName, new StringMemberValue((String) value, cp));
            else if (int.class.isAssignableFrom(returnType))
                annotation.addMemberValue(attrName, new IntegerMemberValue(cp,(Integer)value));
            else if (boolean.class.isAssignableFrom(returnType))
                annotation.addMemberValue(attrName, new BooleanMemberValue((boolean) value, cp));
            else if (String[].class.isAssignableFrom(returnType)){
                String[] stres = (String[])value;
                StringMemberValue[] elements = new StringMemberValue[stres.length];
                for(int i=0;i<stres.length;i++)
                    elements[i] = new StringMemberValue(stres[i],cp);
                ArrayMemberValue amv = new ArrayMemberValue(cp);
                amv.setValue(elements);
                annotation.addMemberValue(attrName,amv);
            }else
                return false;

            attribute.setAnnotation(annotation);
            methodInfo.addAttribute(attribute);
            return true;
        }
        return false;
    }
}

3、修改日志切面类

import com.chen.annotation.JournalLog;
import com.chen.exception.CustomException;
import com.chen.staticInfos.StaticInfo;
import com.chen.utils.AnnotationUtils;
import com.chen.utils.JournalUtils;
import javassist.NotFoundException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;


/**
 * 日志切面
 * Created by 陈梓平 on 2017/9/11.
 */
@Component
@Aspect
public class JournalAspect {
    /**日志输出*/
    private static final Logger logger = LoggerFactory.getLogger(JournalAspect.class);

    /**日志工具类*/
    @Autowired
    private JournalUtils aspectJournalUtils;

    /**service层切面*/
    private final String POINT_CUT = "execution(* com.chen.service..*(..))";

    @Pointcut(POINT_CUT)
    private void pointcut(){}

    /**
     * 后置最终通知(目标方法只要执行完了就会执行后置通知方法)
     * 日志管理
     * @param joinPoint
     */
    @After(value = "pointcut()")
    @Transactional
    public void doAfterAdvice(JoinPoint joinPoint) throws CustomException, ClassNotFoundException, NotFoundException, NoSuchMethodException {
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        int modulerType = -1;
        int opreationType = -1;

        modulerType = (int) AnnotationUtils.get().getAnnotationAttr(className, methodName, JournalLog.class, StaticInfo.AOP_LOG_ATTR_NAME1);
        opreationType = (int) AnnotationUtils.get().getAnnotationAttr(className, methodName, JournalLog.class, StaticInfo.AOP_LOG_ATTR_NAME2);

        //3.添加日志
        if (modulerType!=-1&&opreationType!=-1)
            //TODO 3.1 从请求获取用户id
            aspectJournalUtils.addJournalInfo(modulerType,opreationType, 10086);
    }
}

代码链接:https://git.oschina.net/CatalpaFlat/JouranlDemo3.git

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring Boot中,我们可以使用@Aspect注解来定义一个切面类。切面类是用来定义切面的类,其中可以包含各种通知和切点的定义。在切面类中,我们可以使用@Pointcut注解定义一个切点,用来指定哪些方法会被切入。然后,我们可以使用@Before、@After、@Around等注解来定义各种通知,例如在方法执行之前或之后执行某些逻辑。最后,我们需要在切面类上使用@Aspect注解,将其标识为一个切面类。通过这样的方式,我们可以在Spring Boot项目中使用@Aspect注解来实现AOP的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [SpringBoot项目中使用AOP(面向切面编程技术)即使用@Aspect](https://blog.csdn.net/weixin_38340467/article/details/108150421)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [SpringBoot @Aspect注解详情](https://blog.csdn.net/DuShiWoDeCuo/article/details/78180803)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值