Шаблон проектирования для входа и выхода из методов? - PullRequest
3 голосов
/ 06 апреля 2019

У меня есть общий вопрос о дизайне и архитектуре.После рассмотрения шаблонов проектирования (декораторы, цепочка команд и т. Д.) Мне все еще неясно.

Требование: я хотел бы регистрировать как вход, так и выход моих методов.

На данный момент все мои методы выглядят следующим образом:

public SomeReturnType someMethod1( SomeParameter someParameter ) {
    LOGGER.info( "{someMethod1}[START someMethod1 compute]" );

    doSomeComputationFor(someParameter);
    SomeReturnType result = getSomeResult();

    LOGGER.info( "{someMethod1}[END someMethod1 compute]" );

    return result;
}

public SomeOtherReturnType someMethod2( SomeOtherParameter someOtherParameter ) {
    LOGGER.info( "{someMethod2}[START someMethod2 compute]" );

    maybeDoSomeDBOperation(someOtherParameter);
    SomeOtherReturnType result = getSomeOtherResult();

    LOGGER.info( "{someMethod2}[END someMethod2 compute]" );

    return result;
}

(ниже журнала я также использую некоторую библиотеку KPI для отправки некоторой метки времени, например StatsD)

Все структурына самом деле в форме:

public Foo method( Bar bar ) {
    //1 do some logging as the method starts, and also send some KPI
    LOGGER.info( "{method}[START method compute]" );

    //2 do some computation and actual business logic

    //3 do some logging the confirm the mothods has reached the end + send some other KPI like time elapsed
    LOGGER.info( "{method}[END method compute]" );

    return result;
}

Теперь, глядя на мой проект, у меня есть несколько 290 методов, которые следуют ТОЧНОЙ структуре.

Есть ли умный способ решить эту проблему?Может быть, с хорошим рисунком?Некоторые аннотации?Аспекты?Я открыт для предложений, так как считаю, что определенно есть лучшее решение, чем мое текущее.

1 Ответ

3 голосов
/ 06 апреля 2019

Возможное решение - использование инжектора зависимостей + аннотации.

Здесь приведен пример того, как реализовать то, что вы хотите, используя Сварка в приложении JavaSE.

Вам нужно добавить эту зависимость:

<dependency>
    <groupId>org.jboss.weld.se</groupId>
    <artifactId>weld-se-core</artifactId>
    <version>3.1.0.Final</version>
</dependency>

Затем создайте аннотацию, которая будет использоваться для указания тех методов, которые вы хотите регистрировать.

package org.loggable;

import javax.interceptor.InterceptorBinding;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE, ElementType.METHOD})
@Inherited
@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
public @interface Loggable {
}

Создание перехватчика

package org.loggable;

import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
import java.util.logging.Logger;

@Loggable
@Interceptor
public class LoggableInterceptor {

    @AroundInvoke
    public Object logMethod(InvocationContext context) throws Exception {
        Logger logger = Logger.getLogger(context.getTarget().getClass().getSimpleName());

        logger.info("Starting method: " + context.getMethod().getName());
        Object response = context.proceed();
        logger.info("Finished method: " + context.getMethod().getName());
        return response;

    }
}

Как видите, @AroundInvoke позволяет нам контролировать при входе в метод и при выходе из него.

Мы должны сообщить Weld, что существует новый Interceptor, мы делаем это, добавляя beans.xml вПапка META-INF.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
       http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       bean-discovery-mode="all">
    <interceptors>
        <class>org.loggable.LoggableInterceptor</class>
    </interceptors>
</beans>

Наконец, нам нужно вызвать нашу сущность через Weld, так как она отвечает за создание и выполнение перехватчиков.

package org.loggable;

import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;
import java.io.IOException;
import java.util.logging.Logger;

public class Main {
    public static void main(String... args) throws IOException {
        SeContainer seContainer = SeContainerInitializer.newInstance()
                .initialize();

        Main main = seContainer.select(Main.class).get();
        main.loggableMethod();

        seContainer.close();
    }


    @Loggable
    public void loggableMethod() {
        Logger.getLogger(Main.class.getSimpleName()).info("Inside method.");
    }
}

И вы получите вывод, подобный:

[2019-04-06 11:07:20] [INFO   ] Starting method: loggableMethod 
[2019-04-06 11:07:20] [INFO   ] Inside method. 
[2019-04-06 11:07:20] [INFO   ] Finished method: loggableMethod 

Это структура проекта в случае необходимости.

Project structure

Примечание: В случаевы находитесь в проекте JavaEE, все, что связано с созданием сварных швов, управляется вашим контейнером.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...