zoukankan      html  css  js  c++  java
  • 基于Spring aop 和JAVA注解方式添加日志

    前几天做项目时,在做系统日志这一块,都是在每个方法里手写代码来添加,觉得很繁琐,考虑到spring有aop的功能,便寻思着用AOP来做这个日志功能。

    首先需要传入日志记录的具体操作名称,我们可以用java的注解功能来带入参数,代码如下:

    /** 
    * 类的方法描述注解
    * @author LuoYu
    */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    public @interface Log {

    /** 要执行的操作类型比如:add操作 **/
    public String operationType() default "";

    /** 要执行的具体操作比如:【添加仓库】 **/
    public String operationName() default "";

    }

    注解类编写好之后,就要考虑spring我切面的问题目了,首先我们要创建一个切点,也就是需要插入的代码块,代码如下:

    /** 
    * 通过Spring AOP来添加系统日志 
    * @author LuoYu 
    */ 
    public class LogAspect extends BaseAction{  
    
    private static final long serialVersionUID = -5063868902693772455L;  
    
    private Log logger = LogFactory.getLog(LogAspect.class);  
    
    @SuppressWarnings( { "rawtypes", "unchecked" } )  
    public void doSystemLog(JoinPoint point) throws Throwable {    
            Object[] param = point.getArgs();  
            Method method = null;  
            String methodName = point.getSignature().getName();    
    if (!(methodName.startsWith("set") || methodName.startsWith("get")||methodName.startsWith("query"))){  
                Class targetClass = point.getTarget().getClass();    
                method = targetClass.getMethod(methodName, param[0].getClass());  
    if (method != null) {  
    boolean hasAnnotation = method.isAnnotationPresent(com.tlj.pcxt.common.logaop.Log.class);    
    if (hasAnnotation) {  
                        com.tlj.pcxt.common.logaop.Log annotation = method.getAnnotation(com.tlj.pcxt.common.logaop.Log.class);    
                        String methodDescp = annotation.operationType()+annotation.operationName();  
    if (logger.isDebugEnabled()) {    
                            logger.debug("Action method:" + method.getName() + " Description:" + methodDescp);    
                        }    
                        User appUser=(User) this.getHttpServletRequest().getSession().getAttribute("user");  
    if(appUser!=null){    
    try{    
                                com.tlj.pcxt.entity.admin.Log logInfo=new com.tlj.pcxt.entity.admin.Log();    
                                logInfo.setIp(this.getHttpServletRequest().getRemoteAddr());  
                                logInfo.setSubmitUser(appUser);  
                                logInfo.setContent(annotation.operationType()+","+appUser.getUserName()+  
    "执行【"+annotation.operationName()+"】操作,影响数据的ID集合为["+getID(param[0])+"]");  
    this.logService.save(logInfo);    
                            }catch(Exception ex){    
                                logger.error(ex.getMessage());    
                            }    
                        }    
                    }    
                }    
            }    
        }  
    /** 
         * 通过java反射来从传入的参数object里取出我们需要记录的id,name等属性, 
         * 此处我取出的是id 
         *@author 罗宇 
         *@date 2013-4-11 
         *@param obj 
         *@return 
         *@return String 
         */ 
    public String getID(Object obj){  
    if(obj instanceof String){  
    return obj.toString();  
            }  
            PropertyDescriptor pd = null;  
            Method method = null;  
            String v = "";  
    try{  
                pd = new PropertyDescriptor("id", obj.getClass());  
                method = pd.getReadMethod();    
                v = String.valueOf(method.invoke(obj));   
            }catch (Exception e) {  
                e.printStackTrace();  
            }  
    return v;  
        }  
    }  

    切入代码编写好之后,需要在applicatioContext.xml里配置切入规则,也就是说要在哪些方法执行的时候来切入上面编写的代码:配置如 下:

    <aop:aspectj-autoproxy/> 
    <bean id="logAspect" class="com.tlj.pcxt.common.logaop.LogAspect"/> 
    <aop:config> 
    <aop:aspect ref="logAspect"> 
    <aop:pointcut id="logPointCut" expression="  
                       (execution(* com.tlj.pcxt.service.*.*Impl.add*(..)))  
                    or (execution(* com.tlj.pcxt.service.*.*Impl.update*(..)))  
                    or (execution(* com.tlj.pcxt.service.*.*Impl.delete*(..)))  
                "/> 
    <aop:after pointcut-ref="logPointCut" method="doSystemLog"/> 
    </aop:aspect> 
    </aop:config>

    在此我配置的时在方法执行之后插入代码块

    Xml代码

    1. <aop:after pointcut-ref="logPointCut" method="doSystemLog"/>

    并且是在所有以add,update,delete开头的方法才执行,其余的方法将不再匹配。

    调用方法如下,

    @Log(operationType="add操作:",operationName="添加仓库房间")  
    public void addWareHouseRoom(WareHouseRoom wareHouseRoom) throws ServiceException {  
    try{  
    this.getWareHouseRoomDao().save(wareHouseRoom);  
        }catch (Exception e) {  
    throw new ServiceException(e);  
        }  
    }  

    是在方法头前添加上面自定义的@Log注解,传入相关日志信息

    另外,在LogAspect的doSystemLog方法里的

    1. Object[] param = point.getArgs(); 

    就是取出所匹配方法传入的参数,我们记录日志所需要的相关参数就是从这个对象里取出来的,并且在该方法下面的代码会检查所匹配的方法是否有注解@log,如果没有,会直接跳出该方法,不做任何处理.

  • 相关阅读:
    【推荐】英国金融时报推荐的数据可视化图表分类图
    华为方舟编译器开源官网正式上线
    PyTorch官方教程中文版
    《一张图看懂华为云BigData Pro鲲鹏大数据解决方案》
    区块链学习笔记:DAY05 如何使用公有云区块链服务
    python一行写不下,变多行
    python 多窗口编辑
    ant的设置properties
    java的输出类
    python的IndentationError: unexpected indent python
  • 原文地址:https://www.cnblogs.com/lslvxy/p/3016083.html
Copyright © 2011-2022 走看看