基于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,如果没有,会直接跳出该方法,不做任何处理.

你可能感兴趣的:(spring aop)