аннотация java в сочетании с spring aop для автоматического вывода журнала

Spring

auto-log

auto-logЭто система автоматического мониторинга журналов, разработанная для java.

творческая цель

Я часто пишу какие-то инструменты, и иногда очень хлопотно вручную добавлять какие-то логи, а введение 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;

}

Базовая реализация АОП

Класс 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Свойства описываются следующим образом:

Атрибуты тип По умолчанию инструкция
param boolean true Печатать ли входные параметры
result boolean true Распечатывать ли параметры
costTime boolean false Требуется ли время для печати
exception boolean true Печатать ли исключение
slowThresholdMills long -1 Когда это значение больше или равно 0, а потребление времени превышает сконфигурированное значение, будет выведен журнал медленной работы.

Весенняя интеграция

Полная ссылка на пример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: После github.com/ половина / авто- ...

Gitee: git ee.com/houbinbin/ah...

Добро пожаловать в форк/звезду~

在这里插入图片描述