spring AOP自定义注解方式实现日志管理

在applicationContext-mvc.xml中要添加的

 <mvc:annotation-driven />
 <!-- 激活组件扫描功能,在包com.gcx及其子包下面自动扫描通过注解配置的组件 -->
 <context:component-scan base-package="com.gcx" />



 <!-- 启动对@AspectJ注解的支持 -->
 <!-- proxy-target-class等于true是强制使用cglib代理,proxy-target-class默认是false,如果你的类实现了接口 就走JDK代理,如果没有,走cglib代理  -->
 <!-- 注:对于单利模式建议使用cglib代理,虽然JDK动态代理比cglib代理速度快,但性能不如cglib -->

 <!--如果不写proxy-target-class="true"这句话也没问题-->
 <aop:aspectj-autoproxy proxy-target-class="true"/>

 <!--切面-->
 <bean id="systemLogAspect" class="com.gcx.annotation.SystemLogAspect"></bean>

接下来开始编写代码。
创建日志类实体

public class SystemLog {
    private String id;

    private String description;

    private String method;

    private Long logType;

    private String requestIp;

    private String exceptioncode;

    private String exceptionDetail;

    private String params;

    private String createBy;

    private Date createDate;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id == null ? null : id.trim();
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description == null ? null : description.trim();
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method == null ? null : method.trim();
    }

    public Long getLogType() {
        return logType;
    }

    public void setLogType(Long logType) {
        this.logType = logType;
    }

    public String getRequestIp() {
        return requestIp;
    }

    public void setRequestIp(String requestIp) {
        this.requestIp = requestIp == null ? null : requestIp.trim();
    }

    public String getExceptioncode() {
        return exceptioncode;
    }

    public void setExceptioncode(String exceptioncode) {
        this.exceptioncode = exceptioncode == null ? null : exceptioncode.trim();
    }

    public String getExceptionDetail() {
        return exceptionDetail;
    }

    public void setExceptionDetail(String exceptionDetail) {
        this.exceptionDetail = exceptionDetail == null ? null : exceptionDetail.trim();
    }

    public String getParams() {
        return params;
    }

    public void setParams(String params) {
        this.params = params == null ? null : params.trim();
    }

    public String getCreateBy() {
        return createBy;
    }

    public void setCreateBy(String createBy) {
        this.createBy = createBy == null ? null : createBy.trim();
    }

    public Date getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Date createDate) {
        this.createDate = createDate;
    }
}
 编写dao接口
package com.gcx.dao;

import com.gcx.entity.SystemLog;

public interface SystemLogMapper {
    int deleteByPrimaryKey(String id);

    int insert(SystemLog record);

    int insertSelective(SystemLog record);

    SystemLog selectByPrimaryKey(String id);

    int updateByPrimaryKeySelective(SystemLog record);

    int updateByPrimaryKey(SystemLog record);
}

编写service层

package com.gcx.service;

import com.gcx.entity.SystemLog;

public interface SystemLogService {

    int deleteSystemLog(String id);

    int insert(SystemLog record);
    
    int insertTest(SystemLog record);

    SystemLog selectSystemLog(String id);
    
    int updateSystemLog(SystemLog record);
}

编写service实现类serviceImpl

package com.gcx.service.impl;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.gcx.annotation.Log;
import com.gcx.dao.SystemLogMapper;
import com.gcx.entity.SystemLog;
import com.gcx.service.SystemLogService;

@Service("systemLogService")
public class SystemLogServiceImpl implements SystemLogService {

    @Resource
    private SystemLogMapper systemLogMapper;
    
    @Override
    public int deleteSystemLog(String id) {
        
        return systemLogMapper.deleteByPrimaryKey(id);
    }

    @Override
    
    public int insert(SystemLog record) {
        
        return systemLogMapper.insertSelective(record);
    }

    @Override
    public SystemLog selectSystemLog(String id) {
        
        return systemLogMapper.selectByPrimaryKey(id);
    }

    @Override
    public int updateSystemLog(SystemLog record) {
        
        return systemLogMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public int insertTest(SystemLog record) {
        
        return systemLogMapper.insert(record);
    }

}

到这里基本程序编写完毕

下面开始自定义注解

package com.gcx.annotation;

import java.lang.annotation.*;

@Target({ElementType.PARAMETER, ElementType.METHOD})  
@Retention(RetentionPolicy.RUNTIME)  
@Documented  
public @interface Log {

    /** 要执行的操作类型比如:add操作 **/  
    public String operationType() default "";  
     
    /** 要执行的具体操作比如:添加用户 **/  
    public String operationName() default "";
}

下面编写切面

package com.gcx.annotation;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.UUID;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.gcx.entity.SystemLog;
import com.gcx.entity.User;
import com.gcx.service.SystemLogService;
import com.gcx.util.JsonUtil;

/**
 * @author 杨建 
 * @E-mail: email
 * @version 创建时间:2015-10-19 下午4:29:05
 * @desc 切点类 
 */

@Aspect
@Component
public class SystemLogAspect {

    //注入Service用于把日志保存数据库  
    @Resource  //这里我用resource注解,一般用的是@Autowired,他们的区别如有时间我会在后面的博客中来写
    private SystemLogService systemLogService;  
    
    private  static  final Logger logger = LoggerFactory.getLogger(SystemLogAspect. class);  
    
    //Controller层切点  
    @Pointcut("execution (* com.gcx.controller..*.*(..))")  
    public  void controllerAspect() {  
    }  
    
    /** 
     * 前置通知 用于拦截Controller层记录用户的操作 
     * 
     * @param joinPoint 切点 
     */ 
    @Before("controllerAspect()")
    public void doBefore(JoinPoint joinPoint) {
        System.out.println("==========执行controller前置通知===============");
        if(logger.isInfoEnabled()){
            logger.info("before " + joinPoint);
        }
    }    
    
    //配置controller环绕通知,使用在方法aspect()上注册的切入点
      @Around("controllerAspect()")
      public void around(JoinPoint joinPoint){
          System.out.println("==========开始执行controller环绕通知===============");
          long start = System.currentTimeMillis();
          try {
              ((ProceedingJoinPoint) joinPoint).proceed();
              long end = System.currentTimeMillis();
              if(logger.isInfoEnabled()){
                  logger.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms!");
              }
              System.out.println("==========结束执行controller环绕通知===============");
          } catch (Throwable e) {
              long end = System.currentTimeMillis();
              if(logger.isInfoEnabled()){
                  logger.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms with exception : " + e.getMessage());
              }
          }
      }
    
    /** 
     * 后置通知 用于拦截Controller层记录用户的操作 
     * 
     * @param joinPoint 切点 
     */  
    @After("controllerAspect()")  
    public  void after(JoinPoint joinPoint) {  
  
       /* HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();  
        HttpSession session = request.getSession();  */
        //读取session中的用户  
       // User user = (User) session.getAttribute("user");  
        //请求的IP  
        //String ip = request.getRemoteAddr();
        User user = new User();
        user.setId(1);
        user.setName("张三");
        String ip = "127.0.0.1";
         try {  
            
            String targetName = joinPoint.getTarget().getClass().getName();  
            String methodName = joinPoint.getSignature().getName();  
            Object[] arguments = joinPoint.getArgs();  
            Class targetClass = Class.forName(targetName);  
            Method[] methods = targetClass.getMethods();
            String operationType = "";
            String operationName = "";
             for (Method method : methods) {  
                 if (method.getName().equals(methodName)) {  
                    Class[] clazzs = method.getParameterTypes();  
                     if (clazzs.length == arguments.length) {  
                         operationType = method.getAnnotation(Log.class).operationType();
                         operationName = method.getAnnotation(Log.class).operationName();
                         break;  
                    }  
                }  
            }
            //*========控制台输出=========*//  
            System.out.println("=====controller后置通知开始=====");  
            System.out.println("请求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType);  
            System.out.println("方法描述:" + operationName);  
            System.out.println("请求人:" + user.getName());  
            System.out.println("请求IP:" + ip);  
            //*========数据库日志=========*//  
            SystemLog log = new SystemLog();  
            log.setId(UUID.randomUUID().toString());
            log.setDescription(operationName);  
            log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType);  
            log.setLogType((long)0);  
            log.setRequestIp(ip);  
            log.setExceptioncode( null);  
            log.setExceptionDetail( null);  
            log.setParams( null);  
            log.setCreateBy(user.getName());  
            log.setCreateDate(new Date());  
            //保存数据库  
            systemLogService.insert(log);  
            System.out.println("=====controller后置通知结束=====");  
        }  catch (Exception e) {  
            //记录本地异常日志  
            logger.error("==后置通知异常==");  
            logger.error("异常信息:{}", e.getMessage());  
        }  
    } 
    
    //配置后置返回通知,使用在方法aspect()上注册的切入点
      @AfterReturning("controllerAspect()")
      public void afterReturn(JoinPoint joinPoint){
          System.out.println("=====执行controller后置返回通知=====");  
              if(logger.isInfoEnabled()){
                  logger.info("afterReturn " + joinPoint);
              }
      }
    
    /** 
     * 异常通知 用于拦截记录异常日志 
     * 
     * @param joinPoint 
     * @param e 
     */  
     @AfterThrowing(pointcut = "controllerAspect()", throwing="e")  
     public  void doAfterThrowing(JoinPoint joinPoint, Throwable e) {  
        /*HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();  
        HttpSession session = request.getSession();  
        //读取session中的用户  
        User user = (User) session.getAttribute(WebConstants.CURRENT_USER);  
        //获取请求ip  
        String ip = request.getRemoteAddr(); */ 
        //获取用户请求方法的参数并序列化为JSON格式字符串  
        
        User user = new User();
        user.setId(1);
        user.setName("张三");
        String ip = "127.0.0.1";
        
        String params = "";  
         if (joinPoint.getArgs() !=  null && joinPoint.getArgs().length > 0) {  
             for ( int i = 0; i < joinPoint.getArgs().length; i++) {  
                params += JsonUtil.getJsonStr(joinPoint.getArgs()[i]) + ";";  
            }  
        }  
         try {  
             
             String targetName = joinPoint.getTarget().getClass().getName();  
             String methodName = joinPoint.getSignature().getName();  
             Object[] arguments = joinPoint.getArgs();  
             Class targetClass = Class.forName(targetName);  
             Method[] methods = targetClass.getMethods();
             String operationType = "";
             String operationName = "";
              for (Method method : methods) {  
                  if (method.getName().equals(methodName)) {  
                     Class[] clazzs = method.getParameterTypes();  
                      if (clazzs.length == arguments.length) {  
                          operationType = method.getAnnotation(Log.class).operationType();
                          operationName = method.getAnnotation(Log.class).operationName();
                          break;  
                     }  
                 }  
             }
             /*========控制台输出=========*/  
            System.out.println("=====异常通知开始=====");  
            System.out.println("异常代码:" + e.getClass().getName());  
            System.out.println("异常信息:" + e.getMessage());  
            System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType);  
            System.out.println("方法描述:" + operationName);  
            System.out.println("请求人:" + user.getName());  
            System.out.println("请求IP:" + ip);  
            System.out.println("请求参数:" + params);  
               /*==========数据库日志=========*/  
            SystemLog log = new SystemLog();
            log.setId(UUID.randomUUID().toString());
            log.setDescription(operationName);  
            log.setExceptioncode(e.getClass().getName());  
            log.setLogType((long)1);  
            log.setExceptionDetail(e.getMessage());  
            log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));  
            log.setParams(params);  
            log.setCreateBy(user.getName());  
            log.setCreateDate(new Date());  
            log.setRequestIp(ip);  
            //保存数据库  
            systemLogService.insert(log);  
            System.out.println("=====异常通知结束=====");  
        }  catch (Exception ex) {  
            //记录本地异常日志  
            logger.error("==异常通知异常==");  
            logger.error("异常信息:{}", ex.getMessage());  
        }  
         /*==========记录本地异常日志==========*/  
        logger.error("异常方法:{}异常代码:{}异常信息:{}参数:{}", joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName(), e.getClass().getName(), e.getMessage(), params);  
  
    }  
    
}

前置通知,环绕通知,后置通知,异常通知,后置饭后通知,都写上了,在我们实际编写中不写全也没事,我习惯上把记录日志的逻辑写在后置通知里面,我看网上也有些在前置通知里面的,但我感觉写在后置通知里比较好。

下面开始在controller中加入自定义的注解!!

package com.gcx.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.gcx.annotation.Log;
import com.gcx.service.UserService;

@Controller
@RequestMapping("userController")
public class UserController {

    @Autowired
    private UserService userService;
    
    @RequestMapping("testAOP")
    @Log(operationType="add操作:",operationName="添加用户")  
    public void testAOP(String userName,String password){        
        userService.addUser(userName, password);
    }
}

下面编写测试类

@Test
    public void testAOP1(){
        //启动Spring容器        
        ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"classpath:applicationContext-mvc.xml","classpath:applicationContext-dataSource.xml"});
        //获取service或controller组件
        UserController userController = (UserController) ctx.getBean("userController");
        userController.testAOP("zhangsan", "123456");
    }

测试结果
数据库数据:
在这里插入图片描述
我原本想写两个切点,一个是service层,一个是controller层,service层是用来记录异常信息的日志,而controller层的是用来记录功能的日志,运行结果如下。
在这里插入图片描述
转自博客园-链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring AOP是一种利用代理机制实现面向切面编程的框架。它可以通过自定义注解实现一些特定的逻辑。在Spring AOP中,我们可以通过在自定义注解上添加相关的切点表达式和通知方法来实现对目标方法的增强。这样可以实现一些横切关注点的统一处理,如记录系统日志、权限校验等。通过使用Spring AOP和自定义注解,我们可以更加灵活地对代码进行管理和维护。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [spring aop定义注解保存操作日志到mysql数据库 源码](https://download.csdn.net/download/y_h_d/48993109)[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_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Spring AOP定义注解实现代码](https://download.csdn.net/download/weixin_38714637/12781779)[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_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [spring AOP定义注解方式实现日志管理的实例讲解](https://download.csdn.net/download/weixin_38552536/12764634)[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_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值