有时候,我们在做项目时会遇到这样的需求:
给XXX.java中的所有方法加上指定格式的日志输出。
针对这种指定类、或者指定方法进行共性操作的功能,我们完全可以使用Spring AOP来实现。
本文使用注解方式:
步骤如下:
1 package com.longti.ydgj.util; 2 3 import java.util.LinkedHashMap; 4 5 6 import org.aspectj.lang.JoinPoint; 7 import org.aspectj.lang.annotation.Aspect; 8 import org.aspectj.lang.annotation.Before; 9 import org.aspectj.lang.annotation.Pointcut; 10 import org.slf4j.Logger; 11 import org.slf4j.LoggerFactory; 12 13
14 @Aspect // 指定当前类为切面类 15 public class MatchLogAspect { 16 17 private static final Logger logger = LoggerFactory.getLogger(MatchLogAspect. class); 18 19 // 指定切入点表单式: 拦截哪些方法; 即为哪些类生成代理对象 20 @Pointcut("execution(* com.longti.ydgj.webservice.impl.MatchWebServiceImpl.*(..))") 21 public void pointCut_1(){ 22 } 23 24 // 前置通知 : 在执行目标方法之前执行 25 @Before("pointCut_1()") 26 public void printLog1(JoinPoint joinPoint){ 27 try{ 28 String methodName=joinPoint.getTarget().getClass()+"."+joinPoint.getSignature().getName() + "()"; 29 logger.info(methodName+"--请求参数开始--->"); 30 if(joinPoint.getArgs().length>0){ 31 for (int i = 0; i < joinPoint.getArgs().length; i++) { 32 LinkedHashMap<String, Object> jsonParam=(LinkedHashMap<String, Object>)joinPoint.getArgs()[i]; 33 if(jsonParam.size()>0){ 34 for(String key:jsonParam.keySet()){ 35 StringBuffer sb=new StringBuffer(); 36 sb.append(key+"--=>"); 37 sb.append(jsonParam.get(key)==null?"":jsonParam.get(key).toString()); 38 logger.info(sb.toString()); 39 } 40 } 41 } 42 } 43 logger.info(methodName+"--请求参数结束--->"); 44 }catch(Exception e){ 45 e.printStackTrace(); 46 } 47 } 48 49 50 51 52 }
在切面类中定义切入点,以及拦截方法后进行的操作。
设置好了切面类之后,需要在spring配置文件中进行相关aop配置:
1.开启注解扫描:
<context:component-scan base-package="com.longti.ydgj.util" />
2.
<!-- 开启aop注解方式 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
3.
如果切面类没有使用@Component来创建实例的话,则需要在spring配置文件中声明bean
<!--切面-->
<bean id="matchLogAspect" class="com.longti.ydgj.util.MatchLogAspect"></bean>
综上,搞定。
切入点表达式讲解(以xml方式配置为例):
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- dao 实例 --> <bean id="userDao" class="cn.itcast.g_pointcut.UserDao"></bean> <bean id="orderDao" class="cn.itcast.g_pointcut.OrderDao"></bean> <!-- 切面类 --> <bean id="aop" class="cn.itcast.g_pointcut.Aop"></bean> <!-- Aop配置 --> <aop:config> <!-- 定义一个切入点表达式: 拦截哪些方法 --> <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.*.*(..))" id="pt"/>--> <!-- 【拦截所有public方法】 --> <!--<aop:pointcut expression="execution(public * *(..))" id="pt"/>--> <!-- 【拦截所有save开头的方法 】 --> <!--<aop:pointcut expression="execution(* save*(..))" id="pt"/>--> <!-- 【拦截指定类的指定方法, 拦截时候一定要定位到方法】 --> <!--<aop:pointcut expression="execution(public * cn.itcast.g_pointcut.OrderDao.save(..))" id="pt"/>--> <!-- 【拦截指定类的所有方法】 --> <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.*(..))" id="pt"/>--> <!-- 【拦截指定包,以及其自包下所有类的所有方法】 --> <!--<aop:pointcut expression="execution(* cn..*.*(..))" id="pt"/>--> <!-- 【多个表达式】 --> <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) || execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>--> <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) or execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>--> <!-- 【取非值】 --> <aop:pointcut expression=" not execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/> <!-- 切面 --> <aop:aspect ref="aop"> <!-- 环绕通知 --> <aop:around method="around" pointcut-ref="pt"/> </aop:aspect> </aop:config> </beans>
欢迎讨论。。。