Spring AOP实现日志管理

在一些Web管理系统项目中,日志管理功能也常见,管理系统中日志主要是记录一些谁操作了什么东西,系统是否有异常等信息。那么如何在编程中实现呢?在Java面对对象语言中要实现日志管理功能时,是比较麻烦的。在此,引入了Spring框架中的AOP思想,AOP的主要作用是可以横向插入可重复代码(日志管理),在面向对象语言中是无法做到的,它是面向对象的一种延伸。而AspectJ是AOP的一个纯Java框架,而AspectJ实现AOP有两种方式(要添加相应jar包):一种是基于xml实现,另外一种是基于注解实现。实现日志管理是用基于注解来实现的,因为使用注解方式比较灵活。
在实现功能之前,首先要了解AOP相关的一些术语:
Aspect (切面):在实际应用中,切面通常是指封装的用于横向插入系统功能(如事务、日志等)的类。
Joinpoint (连接点):方法的调用。(调用要记录日志的方法)
Pointcut (切入点):通常是指类名、方法名或者方法上的注解(要记录日志的方法名或者方法上的注解)
Advice(通知/增强处理):可以将其理解为切面类中的方法,它是切面的具体实现(日志类实现方法)。
那么,该如何使用AspectJ基于注解来实现日志管理呢?
实现的大致思路是:
    1.设计日志表和日志类,编写日志Dao和Service以及实现
    2.自定义注解,注解中加入几个属性,属性可以标识操作的类型(方法是做什么的)
    3.编写切面,切点表达式使用上面的注解直接定位到使用注解的方法,
    4.编写通知,通过定位到方法,获取上面的注解以及注解的属性,然后从session中直接获取或者从数据库获取当前登录用户的信息,最后根据业务处理一些日志信息之后调用日志Service存储日志。

  1. 设计相关的日志表,编写相关的接口和接口实现类(Dao、Service)
    在这里插入图片描述
  2. 自定义日志注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogAnnotation {
	String operateType();//记录日志操作类型
}
  1. 编写切面类,注入service层的对象,配置切入点,该切入点是方法上的注解。日志管理使用的是@Around环绕通知,然后通过ProceedingJoinPoint对象来获取到方法(切入点),再通过该方法获取到方法上的注解,获取到注解里面的属性值(日志操作说明)。获取到用户信息,把相关值设置到Log对象中,然后执行ProceedingJoinPoint对象proceed()方法(连接点),然后包Log对象保存到数据库中。
    注意:如果涉及到事务或者自定义异常类还需要在切面类try…catch…捕获异常中的catch抛出异常,给上一级调用者处理,要不然会把异常处理掉,不能抛出。
@Aspect
@Component//声明一个bean
public class LogAspect {
	@Autowired
	private LogService logService;//日志service
	//切入点
	@Pointcut("@annotation(com.koi.annotation.LogAnnotation)")
	public void myPointcut(){}
	//环绕通知 使用@LogAnnotation注解的方法
	@Around("myPointcut()")
	public Object aroundAdvice(ProceedingJoinPoint  pjp) throws Throwable{
		Signature signature = pjp.getSignature();//获取方法签名
		Method method = ( (MethodSignature)signature ).getMethod();//获取方法
		 //这个方法才是目标对象上有注解的方法
		Method declaredMethod = pjp.getTarget().getClass().getDeclaredMethod(signature.getName(), method.getParameterTypes());
		LogAnnotation annotation = declaredMethod.getAnnotation(LogAnnotation.class);//获取方法上的LogAnnotation注解
		String operateType = annotation.operateType();//获取操作说明
		//获取操作用户信息
		Subject subject = SecurityUtils.getSubject();
		UUser user = (UUser)subject.getPrincipal();
		// 创建一个日志对象(准备记录日志)
		Log log=new Log();
		log.setOperateType(operateType);//操作说明
		log.setOperateor(user.getNickname());//设置操作人
		Object obj=null;
		try {
			obj=pjp.proceed();
			log.setOperateResult("操作成功");//设置操作状态
		} catch (CustomException e) {
			log.setOperateResult("操作失败");//设置操作状态
			throw e;//抛给自定义异常处理器处理
		}finally{
			log.setOperateDate(new Date());//设置当前时间
			logService.addLog(log);
		}
		return obj;
	}
}

在需要记录日志的方法(一般是Service实现类的方法)上添加自定义的日志注解@LogAnnotation

@LogAnnotation(operateType="修改密码")
	@Override
	public ResultInfo updatePassword(UUser user, String oldPassword)
			throws Exception {
		.....
	}

最后,在spring.xml容器中(父容器)添加 <aop:aspectj-autoproxy /> 配置,启动对aspectj的支持。
如果日志操作(自定义日志注解)可以在controller控制层方法中执行,该<aop:aspectj-autoproxy />还要配置在spring-mvc.xml容器(子容器)中。因为spring.xml与spring-mvc.xml是父子容器关系,父容器不可以访问到子容器的对象,而子容器可以访问到父容器的对象,但只是针对对象来说,而<aop:aspectj-autoproxy />该配置不是对象,只是开启对aspectj的支持。如果把该配置单单放在父容器中,控制层(spring-mvc.xml子容器)就对aspectj的不支持了,所以应该在父子容器都配置<aop:aspectj-autoproxy />。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值