AOP日志

转载亲的:http://luoyu-ds.iteye.com/blog/1845584 ,

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

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


Java代码  收藏代码

    /**
     * 类的方法描述注解
     * @author LuoYu
     */ 
    @Target(ElementType.METHOD) 
    @Retention(RetentionPolicy.RUNTIME) 
    @Documented 
    @Inherited 
    public @interface Log { 
     
        /** 要执行的操作类型比如:add操作 **/ 
        public String operationType() default ""; 
         
        /** 要执行的具体操作比如:【添加仓库】 **/ 
        public String operationName() default ""; 
         
    } 

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

    /**
     * 通过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里配置切入规则,也就是说要在哪些方法执行的时候来切入上面编写的代码:配置如 下:
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代码  收藏代码

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



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

调用方法如下,


Java代码  收藏代码

    @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方法里的
Java代码  收藏代码

    Object[] param = point.getArgs(); 

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

猜你喜欢

转载自hczwlp.iteye.com/blog/1846171
今日推荐