SpringAOP Aspect注解实现简单日志功能

x33g5p2x  于2021-12-09 转载在 Spring  
字(2.8k)|赞(0)|评价(0)|浏览(287)

SpringAOP实现简单日志功能

AOP(Aspect Oriented Programming):面向切面编程,Spring框架的重要组成部分,利用AOP我们可以将一些公用的业务逻辑部分抽取出来,动态的插入到程序中(如日志记录、权限控制等),降低了各业务逻辑的耦合度。

关于AOP的相关概念这里就不进行讲解了,不了解的可以自行学习下,这里为了方便理解下面代码简单讲解几个概念:

  1. JointPoint(连接点):程序执行中的某个特定的点,例如controller中的访问方法、service中的业务方法等,可以简单理解为调用的方法。
  2. Pointcut(切入点):用来匹配连接点,执行特定的通知 (Advice) 。
  3. Advice(通知):可以简单理解为在before,after,afterReturning,afterThrowing,around中执行的代码。

在开始前首先我们需要在pom.xml中引入一些相关的jar。

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.7.4</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.7.4</version>
</dependency>
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.1</version>
</dependency>

进入代码环节,创建一个切面类LogAspect ,如下:

@Component
@Aspect
public class LogAspect {

    /** * 切入点,使用方法切点函数execution匹配 * * com.xxx.aop.test..*.*(..):表示test包和所有子包里的任意类的任意方法 */
	@Pointcut("execution(* com.xxx.aop.test..*.*(..))")
	public void logPointcut(){}
		
	/** * 后置通知,JointPoint执行完成后执行,不论是否JointPoint异常,实质是finally中的代码块 * @param joinPoint */
	@After("logPointcut()")
	public void doAfter(JoinPoint joinPoint){
		Object[] args = joinPoint.getArgs(); // 参数值
        String[] argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames(); // 参数名
        String methodName = joinPoint.getSignature().getName(); // 获取方法名
		HttpServletRequest request = 
		((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		String ip = request.getRemoteAddr(); // 获取IP地址
	    HttpSession session = request.getSession();
	    User user = (User)session.getAttribute("userCache");//获取用户,根据自身项目实际情况修改
	    //保存日志
		System.out.println("执行保存日志操作...");
	}
}

@After注解的方法是在JointPoint执行完以后执行,如果需要在JointPoint执行前执行某些操作,可以使用@Around注解,使用方法如下:

/** * 环绕通知,在JointPoint执行完成前后执行 * @param pjp * @return * @throws Throwable */
	@Around("logPointcut()")
	public Object doAround(ProceedingJoinPoint pjp) throws Throwable{
		//切入方法执行前的操作
		System.out.println("LogAop Before Advice...");
		//执行joinPoint
		Object obj=pjp.proceed();
		//切入方法执行后的操作
		System.out.println("LogAop After Advice...");
		//必须返回执行结果,不返回会出现404等错误
		return obj;
	}

Spring和SpringMVC的配置文件中都进行如下配置:

<!-- 注意自己的配置中是否存在下面的配置,如果有就无需再配置 -->

<!-- xml命名空间的声明 -->
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation=
"http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"
<!-- 开启aspectj注解 -->
<aop:aspectj-autoproxy />

SpringMVC是Spring的一个子容器,为了解决事务失效问题,我们通常会配置在Spring容器中不扫描@Controller注解,在SpringMvc容器中只扫描@Controller注解。因此,如果不需要切入Controller的话SpringMVC配置文件就不需要进行配置,反之,只切入Controller就不需要配置Spring配置文件。

到此为止,一个简单的日志切面就完成了,日志记录了用户、访问IP、访问方法等信息,但用户并不能通过查看日志中的访问方法知道是操作的哪个菜单,下篇文章讲解[SpringAOP+自定义注解实现日志功能]。

相关文章