SpringAOP +log4J+注解的 日志管理
来源:互联网 发布:诚信荣誉 淘宝网 编辑:程序博客网 时间:2024/05/18 01:35
SpringAOP+log4J+注解 日志管理
by Kay 2017.8.10
在Spring项目中,日志管理的通常方式是采用AOP来实现,以下为我使用SpringAOP进行分类管理的一个Demo,以便总结。
代码下载:https://github.com/LiuKay/AopLog
1.pom.xml 项目依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.kay</groupId> <artifactId>AopLog</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>AopLog</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.version>4.1.3.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.6.12</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.12</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.3</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.7</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.7</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.1.41</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies></project>
2.项目结构
- 基于注解的日志约定,也就是每个被切入方法需要遵循的注解写法,当然不用的话也不必这么麻烦,为了日志的格式统一;其次是通过注解可以获得额外想要获得方法信息(如方法描述,参数列表等)
- 1)日志注解
package com.kay.annotation;import java.lang.annotation.Documented;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * Created by kay on 2017/8/10. */@Retention(RetentionPolicy.RUNTIME)@Target({java.lang.annotation.ElementType.METHOD})@Documentedpublic @interface LogAnnotation { String description() default "";}
- 2)日志实体类,便于存放在数据库
package com.kay.entity;import java.util.Date;/** * Created by kay on 2017/8/10. */public class MyLog { private String invokeMethod; private String methodParams; //private String requestIP; // 如果是web项目可以获取ip private Integer type; private Date invokeTime; private String description; private String exceptionCode; private String exceptionDetail; public String getInvokeMethod() { return invokeMethod; } public void setInvokeMethod(String invokeMethod) { this.invokeMethod = invokeMethod; } public String getMethodParams() { return methodParams; } public void setMethodParams(String methodParams) { this.methodParams = methodParams; } //public String getRequestIP() { // return requestIP; //} //public void setRequestIP(String requestIP) { // this.requestIP = requestIP; //} public Integer getType() { return type; } public void setType(Integer type) { this.type = type; } public Date getInvokeTime() { return invokeTime; } public void setInvokeTime(Date invokeTime) { this.invokeTime = invokeTime; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getExceptionCode() { return exceptionCode; } public void setExceptionCode(String exceptionCode) { this.exceptionCode = exceptionCode; } public String getExceptionDetail() { return exceptionDetail; } public void setExceptionDetail(String exceptionDetail) { this.exceptionDetail = exceptionDetail; } @Override public String toString() { return "日志记录--{" + "执行方法='" + invokeMethod + '\'' + ", 方法参数='" + methodParams + '\'' + ", 日志类型='" + type + '\'' + ", 执行时间=" + invokeTime + ", 方法描述='" + description + '\'' + ", 异常code='" + exceptionCode + '\'' + ", 异常详细='" + exceptionDetail + '\'' + '}'; }}
- 3)日志切面
package com.kay.aop;import com.alibaba.fastjson.JSON;import com.kay.annotation.LogAnnotation;import com.kay.entity.MyLog;import com.kay.service.LogService;import com.kay.service.impl.LogServiceImpl;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.reflect.MethodSignature;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.lang.reflect.Method;import java.util.Date;/** * Created by kay on 2017/8/10. */@Aspectpublic class LogAspect { //此处在实际开发中需要注入一个日志服务,模拟加入数据库 private LogService logService=new LogServiceImpl(); private static final Logger logger = LoggerFactory.getLogger(LogAspect. class); private final int LOG_INFO=0; private final int LOG_EXPETION=1; @Before("@annotation(com.kay.annotation.LogAnnotation)") public void logBefore(JoinPoint joinPoint){ Object[] args = joinPoint.getArgs(); StringBuilder sb = new StringBuilder(); if (args!=null) { for (Object arg : args) { sb.append(JSON.toJSONString(arg)); } } try { //产生数据库日志 MyLog log=new MyLog(); log.setInvokeMethod(getMethodName(joinPoint)); log.setMethodParams(sb.toString()); log.setExceptionCode(null); log.setExceptionDetail(null); log.setType(LOG_INFO); log.setInvokeTime(new Date()); //todo 方法描述 log.setDescription(getMthodDescription(joinPoint)); logService.addLogToDB(log); } catch (Exception e) { logger.error("log dobefore异常"); logger.error(e.getMessage(),e); } //控制台记录 getLogger(joinPoint).info(String.format("start invoke [%s], params = [%s]", new Object[]{getMethodName(joinPoint), sb.toString()})); } @AfterThrowing(value = "@annotation(com.kay.annotation.LogAnnotation)", throwing = "ex") public void logAfterThrowingException(JoinPoint joinPoint,Exception ex){ Object[] args = joinPoint.getArgs(); StringBuilder sb = new StringBuilder(); if (args!=null) { for (Object arg : args) { sb.append(JSON.toJSONString(arg)); } } try { MyLog log=new MyLog(); log.setInvokeMethod(getMethodName(joinPoint)); log.setMethodParams(sb.toString()); log.setExceptionCode(ex.getClass().getName()); log.setExceptionDetail(ex.getMessage()); log.setType(LOG_EXPETION); log.setInvokeTime(new Date()); log.setDescription(getMthodDescription(joinPoint)); logService.addLogToDB(log); } catch (Exception e) { logger.error("log 异常"); logger.error(e.getMessage(),e); } getLogger(joinPoint).error(String.format("error occurred when invoking [%s]",new Object[]{ getMethodName(joinPoint)}), ex); } private Logger getLogger(JoinPoint joinPoint) { return LoggerFactory.getLogger(getFullClassName(joinPoint)); } private String getMethodName(JoinPoint joinPoint) { return ((MethodSignature) joinPoint.getSignature()).getName(); } private String getFullClassName(JoinPoint joinPoint) { return joinPoint.getTarget().getClass().getName(); } /** * 获取切面方法注解上的描述 * @param joinPoint * @return * @throws Exception */ public static String getMthodDescription(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(LogAnnotation. class).description(); break; } } } return description; }}
- 4)LogService 日志服务类,模拟数据库中日志的读取
package com.kay.service.impl;import com.kay.entity.MyLog;import com.kay.service.LogService;import org.springframework.stereotype.Service;import java.util.ArrayList;import java.util.List;/** * Created by kay on 2017/8/10. */@Servicepublic class LogServiceImpl implements LogService {//模拟数据库存放的日志集合 private static List<MyLog> logList=new ArrayList<MyLog>();//打印日志 public void showLogs() { for (MyLog log:logList){ System.out.println(log); } }//存入日志 public void addLogToDB(MyLog log) { logList.add(log); }}
- 5)BusinessService主要为模拟业务逻辑,只有一个test方法
package com.kay.service.impl;import com.kay.annotation.LogAnnotation;import com.kay.service.BusinessService;/** * Created by kay on 2017/8/10. */public class BusinessServiceImpl implements BusinessService { @LogAnnotation(description = "test方法描述") public String test(String param1, String param2) { int i=1/0; //模拟异常 System.out.println("do something..................."); return "end.."; }}
- 6)相关配置
applicationContext.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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> <aop:aspectj-autoproxy /> <bean id="businesService" class="com.kay.service.impl.BusinessServiceImpl" /> <bean id="advice" class="com.kay.aop.LogAspect"/> <bean id="logService" class="com.kay.service.impl.LogServiceImpl"/></beans>
log4j.properties
log4j.rootLogger=DEBUG, A1log4j.appender.A1=org.apache.log4j.ConsoleAppenderlog4j.appender.A1.layout=org.apache.log4j.PatternLayoutlog4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
- 7)测试方法
package com.kay;import com.kay.service.BusinessService;import com.kay.service.LogService;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class MainTest{ public static void main( String[] args ) { ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); BusinessService service= (BusinessService) context.getBean("businesService"); try { service.test("参数1", "参数2"); } catch (Exception e) { System.out.println(e.getClass().getName()); } LogService logService = (LogService) context.getBean("logService"); logService.showLogs(); }}
- 8)测试结果
711 [main] INFO com.kay.service.impl.BusinessServiceImpl - start invoke [test], params = ["参数1""参数2"]712 [main] ERROR com.kay.service.impl.BusinessServiceImpl - error occurred when invoking [test]java.lang.ArithmeticException: / by zero at com.kay.service.impl.BusinessServiceImpl.test(BusinessServiceImpl.java:13) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:52) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168) at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:58) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) at $Proxy9.test(Unknown Source) at com.kay.MainTest.main(MainTest.java:15)java.lang.ArithmeticException714 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'logService'日志记录--{执行方法='test', 方法参数='"参数1""参数2"', 日志类型='0', 执行时间=Thu Aug 10 17:44:04 CST 2017, 方法描述='test方法描述', 异常code='null', 异常详细='null'}日志记录--{执行方法='test', 方法参数='"参数1""参数2"', 日志类型='1', 执行时间=Thu Aug 10 17:44:04 CST 2017, 方法描述='test方法描述', 异常code='java.lang.ArithmeticException', 异常详细='/ by zero'}
参考学习:
http://itindex.net/detail/50710-springaop-controller-service
https://github.com/Liam1206/aop-log-annotation
阅读全文
0 0
- SpringAOP +log4J+注解的 日志管理
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- java SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- java SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- java SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- java SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- java SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- aop:aspectj-autoproxy, SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- iOS armv7, armv7s, arm64区别与应用32位、64位配置
- 最小生成树(2)--Prim算法
- FreeRTOS中打开关闭任务切换
- Postfix扫描邮件结果Action
- html设置控件的背景样式,透明
- SpringAOP +log4J+注解的 日志管理
- 10分钟学会基本的 Flexbox 布局
- Postfix邮件路由
- 微信小程序开发之从相册获取图片 使用相机拍照 本地图片上传
- ActiveMQ的几种消息持久化机制
- 论文阅读理解
- TortoiseSVN文件夹及文件图标不显示解决方法
- shell demo analyse------ 1
- Rspamd配置