java 注解结合 spring aop 实现自动输出日志

java

auto-log 是一款为 java 设计的自动日志监控框架。

创作目的

经常会写一些工具,有时候手动加一些日志很麻烦,引入 spring 又过于大材小用。

所以希望从从简到繁实现一个工具,便于平时使用。

特性

  • 基于注解+字节码,配置灵活

  • 自动适配常见的日志框架

  • 支持编程式的调用

  • 支持注解式,完美整合 spring

  • 支持整合 spring-boot

  • 支持慢日志阈值指定,耗时,入参,出参,异常信息等常见属性指定

变更日志

核心原理

注解定义

import java.lang.annotation.*;

/**

* 自动注解

* @author binbin.hou

* @since 0.0.1

*/

@Target({ElementType.METHOD, ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Inherited

public @interface AutoLog {

/**

* 输出参数

* @return 参数

* @since 0.0.1

*/

boolean param() default true;

/**

* 是否输出结果

* @return 结果

* @since 0.0.1

*/

boolean result() default true;

/**

* 是否输出时间

* @return 耗时

* @since 0.0.1

*/

boolean costTime() default false;

/**

* 是否输出异常信息

* @return 是否

* @since 0.0.6

*/

boolean exception() default true;

/**

* 慢日志阈值

*

* 当值小于 0 时,不进行慢日志统计。

* 当值大于等于0时,当前值只要大于等于这个值,就进行统计。

* @return 阈值

* @since 0.0.4

*/

long slowThresholdMills() default -1;

}

核心 AOP 实现

这里的 LogFactory 类是关键,可以兼容目前大部分的日志框架。

import com.github.houbb.auto.log.annotation.AutoLog;

import com.github.houbb.heaven.response.exception.CommonRuntimeException;

import com.github.houbb.log.integration.core.Log;

import com.github.houbb.log.integration.core.LogFactory;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.Signature;

import org.aspectj.lang.annotation.Around;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Pointcut;

import org.aspectj.lang.reflect.MethodSignature;

import org.springframework.context.annotation.EnableAspectJAutoProxy;

import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

import java.util.Arrays;

/**

* 这是一种写法

* 自动日志输出 aop

* @author binbin.hou

* @since 0.0.3

*/

@Aspect

@Component

@EnableAspectJAutoProxy

public class AutoLogAop {

private static final Log LOG = LogFactory.getLog(AutoLogAop.class);

/**

* 执行核心方法

*

* 相当于 MethodInterceptor

* @param point 切点

* @param autoLog 日志参数

* @return 结果

* @throws Throwable 异常信息

* @since 0.0.3

*/

@Around("@annotation(autoLog)")

public Object around(ProceedingJoinPoint point, AutoLog autoLog) throws Throwable {

Method method = getCurrentMethod(point);

String methodName = method.getName();

try {

final long startMills = System.currentTimeMillis();

//1. 是否输入入参

if (autoLog.param()) {

LOG.info("{} param is {}.", methodName, Arrays.toString(point.getArgs()));

}

//2. 执行方法

Object result = point.proceed();

//3. 结果

if (autoLog.result()) {

LOG.info("{} result is {}.", methodName, result);

}

//3.1 耗时

final long slowThreshold = autoLog.slowThresholdMills();

if (autoLog.costTime() || slowThreshold >= 0) {

final long endMills = System.currentTimeMillis();

long costTime = endMills - startMills;

if (autoLog.costTime()) {

LOG.info("{} cost time is {}ms.", methodName, costTime);

}

//3.2 慢日志

if (slowThreshold >= 0 && costTime >= slowThreshold) {

LOG.warn("{} is slow log, {}ms >= {}ms.", methodName, costTime, slowThreshold);

}

}

return result;

} catch (Throwable e) {

if(autoLog.exception()) {

LOG.error("{} meet ex.", methodName, e);

}

throw e;

}

}

/**

* 获取当前方法信息

*

* @param point 切点

* @return 方法

*/

private Method getCurrentMethod(ProceedingJoinPoint point) {

try {

Signature sig = point.getSignature();

MethodSignature msig = (MethodSignature) sig;

Object target = point.getTarget();

return target.getClass().getMethod(msig.getName(), msig.getParameterTypes());

} catch (NoSuchMethodException e) {

throw new CommonRuntimeException(e);

}

}

}

快速开始

maven 引入

<dependency>

<group>com.github.houbb</group>

<artifact>auto-log-core</artifact>

<version>${最新版本}</version>

</dependency>

入门案例

UserService userService = AutoLogHelper.proxy(new UserServiceImpl());

userService.queryLog("1");

  • 日志如下

[INFO] [2020-05-29 16:24:06.227] [main] [c.g.h.a.l.c.s.i.AutoLogMethodInterceptor.invoke] - public java.lang.String com.github.houbb.auto.log.test.service.impl.UserServiceImpl.queryLog(java.lang.String) param is [1]

[INFO] [2020-05-29 16:24:06.228] [main] [c.g.h.a.l.c.s.i.AutoLogMethodInterceptor.invoke] - public java.lang.String com.github.houbb.auto.log.test.service.impl.UserServiceImpl.queryLog(java.lang.String) result is result-1

代码

其中方法实现如下:

  • UserService.java

public interface UserService {

String queryLog(final String id);

}

  • UserServiceImpl.java

直接使用注解 @AutoLog 指定需要打日志的方法即可。

public class UserServiceImpl implements UserService {

@Override

@AutoLog

public String queryLog(String id) {

return "result-"+id;

}

}

注解说明

核心注解 @AutoLog 的属性说明如下:

属性类型默认值说明
parambooleantrue是否打印入参
resultbooleantrue是否打印出参
costTimebooleanfalse是否打印耗时
exceptionbooleantrue是否打印异常
slowThresholdMillslong-1当这个值大于等于 0 时,且耗时超过配置值,会输出慢日志

spring 整合使用

完整示例参考 SpringServiceTest

注解声明

使用 @EnableAutoLog 启用自动日志输出

@Configurable

@ComponentScan(basePackages = "com.github.houbb.auto.log.test.service")

@EnableAutoLog

public class SpringConfig {

}

测试代码

@ContextConfiguration(classes = SpringConfig.class)

@RunWith(SpringJUnit4ClassRunner.class)

public class SpringServiceTest {

@Autowired

private UserService userService;

@Test

public void queryLogTest() {

userService.queryLog("1");

}

}

  • 输出结果

信息: public java.lang.String com.github.houbb.auto.log.test.service.impl.UserServiceImpl.queryLog(java.lang.String) param is [1]

五月 30, 2020 12:17:51 下午 com.github.houbb.auto.log.core.support.interceptor.AutoLogMethodInterceptor info

信息: public java.lang.String com.github.houbb.auto.log.test.service.impl.UserServiceImpl.queryLog(java.lang.String) result is result-1

五月 30, 2020 12:17:51 下午 org.springframework.context.support.GenericApplicationContext doClose

开源地址

Github: https://github.com/houbb/auto-log

Gitee: https://gitee.com/houbinbin/auto-log

欢迎 fork/star~

以上是 java 注解结合 spring aop 实现自动输出日志 的全部内容, 来源链接: utcz.com/z/394217.html

回到顶部