面向切面编程(AOP)应用,日志切面,基于注解

名词解释:

  • 切面(Aspect) :一个关注点的模块化,这个关注点可能会横切多个对象,在本例中,“切面”就是类SystemLogAspect所的具体行为,例如,“切面”可以在ApplicationContext中<aop:aspect>来配置,或者使用注解@Aspect。
Aspect    //定义一个切面
Component
@Order(1)
public class SystemLogAspect {}
 
或者配置文件:
aop:config>
 		<!-- 定义切面 -->
  		<aop:aspect id="security" ref="securityHandler1">
	  		<!-- 定义pointcut,并写表达式 -->
	   		<aop:pointcut id="allMethod" expression="execution(* managerImpl.UserManagerImpl.add*(..))|| execution(* man											agerImpl.UserManagerImpl.del*(..))"/>
	   		<!-- 定义advice,织入pointcut -->
	   		<aop:before method="checkSecurity" pointcut-ref="allMethod"/>
  		</aop:aspect>
 	</aop:config>


  • 连接点(Joinpoint) :在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候,joinPoint对象进程作为参数使用,从而获取这个连接点的相关信息,例如:可以为通知(Advice)的主体部分获得连接点信息

  • 通知(Advice) :在切面的某个特定的连接点(Joinpoint)上执行的动作,例如前置通知,后置通知,异常通知等等。
  •        通知:即为在向连接点切入时所执行的动作
  • /**  
         * 前置通知 用于拦截Controller层记录用户的操作  
         * joinPoint 切点为参数,可以使通知获取连接点的信息
         */    
        @Before("controllerAspect()")    
         public  void doBefore(JoinPoint joinPoint) { //doSomeThing }

  • 切入点(Pointcut) :匹配连接点的断言,是一个表达式,通知和一个切入点表达式相关联。并在满足这个切入点的连接点上运行,
  •  //Controller层切入点,    
    @Pointcut("@annotation(com.poobo.comm.web.aop.SystemCtrLo4jAop)")
  • public void controllerAspect() { }
    自定义一个注解  表达式:"@annotation(com.poobo.comm.web.aop.SystemCtrLo4jAop)"是一个自定义的注解,切入点的表达式使用这个注解后,只要在一段代码前使用了这个注解,那么该代码就是一个切入点。这样就不仅同一了名称,
  • 而且避免了使用切入点表达式execution(* com.spring.service.*.*(..))的局限性。
  • @Target({ElementType.PARAMETER, ElementType.METHOD})    
    @Retention(RetentionPolicy.RUNTIME)    
    @Documented    
    public @interface SystemCtrLo4jAop {
    	 String description()  default "";
    }
  • 目标对象(Target Object) :一个或者多个切面(aspect)所通知(advise)的对象。Spring AOP采用代理实现,实际AOP操作的是TargetObject的代理对象。
  • AOP代理(AOP Proxy) 在Spring AOP中有两种代理方式,JDK动态代理和CGLIB代理。默认情况下,TargetObject实现了接口时,则采用JDK动态代理,。强制使用CGLIB代理需要将 <aop:config> 的 proxy-target-class 属性设为true
//定义一个切面

@Aspect
@Component
@Order(1)
public class SystemLogAspect {
	
	//系统日志
	@Autowired
	private ISysLogService iSysLogService;
	
	@Autowired
	//系统用户
	private IPrivateAccountService accountService;
	
	//本地异常日志记录对象    
	private Logger log = Logger.getLogger(SystemLogAspect.class);
    
    //Service层切点    
    @Pointcut("@annotation(com.poobo.comm.web.aop.SystemServiceLo4jAop)")    
    public  void serviceAspect() {    
    }    
    
    //Controller层切点    
    @Pointcut("@annotation(com.poobo.comm.web.aop.SystemCtrLo4jAop)")    
    public  void controllerAspect() {    
    }  
   
    
    /**  
     * 前置通知 用于拦截Controller层记录用户的操作  
     *  
     * @param joinPoint 切点  
     */    
    @Before("controllerAspect()")    
     public  void doBefore(JoinPoint joinPoint) {  
        //读取session中的用户    
        SysAccount user =  AppContextUtil.getLoginInfo(); 
        //请求的IP    
        String ip = AppContextUtil.getRequest().getRemoteAddr();    
         try {    
           /* //*========控制台输出=========   
            System.out.println("=====前置通知开始=====");    
            System.out.println("请求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));    
            System.out.println("方法描述:" + getControllerMethodDescription(joinPoint));    
            System.out.println("请求人账号:" + user.getLoginName()); 
            System.out.println("请求人昵称:" + user.getNickName()); 
            System.out.println("请求人角色:" + user.getRole().getName()); 
            System.out.println("请求IP:" + ip);   
            System.out.println("请求时间:"+DateUtil.getNowTime());
           //*========数据库日志=========*/    
            SysLog tbSysLog=new  SysLog();
            tbSysLog.setMethods(getControllerMethodDescription(joinPoint));
            tbSysLog.setLogDesc((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));        
            tbSysLog.setLoginIp(ip); 
            tbSysLog.setRoleName(user.getRole().getName());
            tbSysLog.setAccountName(user.getNickName());
            tbSysLog.setLoginName(user.getLoginName());
            tbSysLog.setCreateDate(DateUtil.getNowTime());
            tbSysLog.setType(WebConstants.SYS_LOG_RECORD);
            //保存数据库    
            iSysLogService.saveSysLog(tbSysLog);
            //System.out.println("=====前置通知结束=====");    
        }  catch (Exception e) {  
            //记录本地异常日志    
            log.error("==前置通知异常==");    
            log.error("异常信息:{}",e);  
        }    
    }    
    
    /**  
     * 异常通知 用于拦截service层记录异常日志  
     *  
     * @param joinPoint  
     * @param e  
     */    
    @AfterThrowing(pointcut = "serviceAspect()", throwing = "e")    
     public  void doAfterThrowing(JoinPoint joinPoint, Throwable e) {    
        
        //读取session中的用户    
        SysAccount user = AppContextUtil.getLoginInfo();    
        //获取请求ip    
        String ip = AppContextUtil.getRequest().getRemoteAddr();    
        //获取用户请求方法的参数并序列化为JSON格式字符串    
        String params = "";    
         if (joinPoint.getArgs() !=  null && joinPoint.getArgs().length > 0) {    
             for ( int i = 0; i < joinPoint.getArgs().length; i++) {    
                params += JSON.toJSONString(joinPoint.getArgs()[i]) + ";";    
            }    
        }    
         try {    
              /*========控制台输出=========*/    
          /*  System.out.println("=====异常通知开始=====");    
            System.out.println("异常代码:" + e.getClass().getName());    
            System.out.println("异常信息:" + e.getMessage());    
            System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));    
            System.out.println("方法描述:" + getServiceMthodDescription(joinPoint));    
            System.out.println("请求人:" + user.getLoginName());    
            System.out.println("请求IP:" + ip);    
            System.out.println("请求参数:" + params);    */
           /*    ==========数据库日志=========   */ 
            SysLog sysLog=new SysLog();
            sysLog.setMethods(getServiceMthodDescription(joinPoint));    
            sysLog.setExceptionCode(e.getClass().getName());    
            sysLog.setType(WebConstants.SYS_LOG_EXCEPTION);    
            sysLog.setLogDesc((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));    
            sysLog.setExceptionDetail(e.getMessage());    
            sysLog.setParams(params);
            sysLog.setCreateBy(user.getLoginName());    
            sysLog.setCreateDate(DateUtil.getNowTime());    
            sysLog.setLoginIp(ip);    
            //保存数据库    
            iSysLogService.saveSysLog(sysLog);    
           // System.out.println("=====异常通知结束=====");    
        }  catch (Exception ex) {    
            //记录本地异常日志    
            log.error("==异常通知异常==");    
            log.error("异常信息:{}", ex);    
        }    
         /*==========记录本地异常日志==========*/    
        // log.error(null,joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName(), e.getClass().getName(), e.getMessage());    
    
    }   
    
    
    /**  
     * 获取注解中对方法的描述信息 用于service层注解  
     *  
     * @param joinPoint 切点  
     * @return 方法描述  
     * @throws Exception  
     */    
     public  static String getServiceMthodDescription(JoinPoint joinPoint)    
             throws Exception {    
        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 description = "";    
         for (Method method : methods) {    
             if (method.getName().equals(methodName)) {    
                Class[] clazzs = method.getParameterTypes();    
                 if (clazzs.length == arguments.length) {    
                    description = method.getAnnotation(SystemServiceLo4jAop.class).description();    
                     break;    
                }    
            }    
        }    
         return description;    
    }    
    
    
    /**  
     * 获取注解中对方法的描述信息 用于Controller层注解  
     *  
     * @param joinPoint 切点  
     * @return 方法描述  
     * @throws Exception  
     */    
     public  static String getControllerMethodDescription(JoinPoint joinPoint)  throws Exception {    
        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 description = "";    
         for (Method method : methods) {    
             if (method.getName().equals(methodName)) {    
                Class[] clazzs = method.getParameterTypes();    
                 if (clazzs.length == arguments.length) {    
                    description = method.getAnnotation(SystemCtrLo4jAop. class).description();    
                     break;    
                }    
            }    
        }    
         return description;    
    }    
}

//自定义注解
/**
 * 自定义aop拦截日志
 * @author xyy
 *
 */
@Target({ElementType.PARAMETER, ElementType.METHOD})    
@Retention(RetentionPolicy.RUNTIME)    
@Documented    
public @interface SystemCtrLo4jAop {
	 String description()  default "";
}

//应用于一个切入点
@RequestMapping(value="admin/goods/ajaxDoDeleteSysGoods",produces="text/html;charset=UTF-8")
	@ResponseBody
	@SystemCtrLo4jAop(description="删除商品")
	public String ajaxDoDeleteSysGoods(SysGoods goods,HttpServletRequest request){
		
		//删除商品
		json = goodsService.deleteGoods(goods);
		
		return json.toJSONString();
	}


当运行切入点时即可在数据库保存一条日志记录





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值