面向切面编程(AOP)应用,日志切面,基于注解
2016-04-19 18:08
393 查看
名词解释:
切面(Aspect) :一个关注点的模块化,这个关注点可能会横切多个对象,在本例中,“切面”就是类SystemLogAspect所的具体行为,例如,“切面”可以在ApplicationContext中<aop:aspect>来配置,或者使用注解@Aspect。
或者配置文件:
连接点(Joinpoint) :在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候,joinPoint对象进程作为参数使用,从而获取这个连接点的相关信息,例如:可以为通知(Advice)的主体部分获得连接点信息
通知(Advice) :在切面的某个特定的连接点(Joinpoint)上执行的动作,例如前置通知,后置通知,异常通知等等。
通知:即为在向连接点切入时所执行的动作
切入点(Pointcut) :匹配连接点的断言,是一个表达式,通知和一个切入点表达式相关联。并在满足这个切入点的连接点上运行,
目标对象(Target Object) :一个或者多个切面(aspect)所通知(advise)的对象。Spring
AOP采用代理实现,实际AOP操作的是TargetObject的代理对象。
AOP代理(AOP Proxy) 在Spring AOP中有两种代理方式,JDK动态代理和CGLIB代理。默认情况下,TargetObject实现了接口时,则采用JDK动态代理,。强制使用CGLIB代理需要将
//定义一个切面
//自定义注解
//应用于一个切入点
当运行切入点时即可在数据库保存一条日志记录
切面(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(); }
当运行切入点时即可在数据库保存一条日志记录
相关文章推荐
- yui3的AOP(面向切面编程)和OOP(面向对象编程)
- JavaScript AOP编程实例
- 使用AOP改善javascript代码
- 初识SmartJS - AOP三剑客
- java使用动态代理来实现AOP(日志记录)的实例代码
- JavaScript之AOP编程实例
- Javascript aop(面向切面编程)之around(环绕)分析
- php笔记之:AOP的应用
- 深入浅析Spring 的aop实现原理
- spring aop两种配置方式
- 实例讲解Java的Spring框架中的AOP实现
- autoload-cache-1.7 发布
- autoload-cache-2.4 发布
- Spring3 AOP配置异常。执行时间记录
- AOP切面编程
- spring 切面memcached的环绕通知
- 淘宝Tprofiler工具实现分析
- 关于HouseMD
- Spring AOP介绍及源码分析
- 基于 Java 语言的极速 WEB + ORM 框架 JFinal 1.6 发布