私は全体的な設計とアーキテクチャ疑問を持っています。デザインパターン(デコレータ、その上のコマンドのチェーン、および)を見た後、それはまだ私には不明です。
要件:私は私のメソッドの入り口と出口の両方をログに記録するようにしたいと思います。
今の時点で、すべての私の方法を次のようになります。
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;
}
(ログの下に、私はまたStatsDのように、いくつかのタイムスタンプを送信するために、いくつかのKPIのライブラリを使用しています)
すべての構造は、本当に、フォームのとおりです。
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のメソッドを持っています。
これを解決する巧妙な方法はありますか?たぶん、素敵なパターンを持ちますか?いくつかの注釈?側面?私は現在のものよりもよりよい解決策は間違いなくそこにあると信じて、私は提案に開いています。
可能な解決策は、あなたの依存関係のインジェクター+注釈を使用しています。
ここではあなたが使用したいものを実装する方法の例持って溶接をする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
の方法と終了を入力するときに私たちが制御することができます。
私たちは、追加することによって、新しいインターセプターがあることを、我々はそうする溶接を通知する必要が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>
最後に、我々はそれがインターセプタを作成し、実行を担当しているようウェルドを通じて当社の実体を呼び出す必要があります。
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
これは、必要な場合にプロジェクト構造です。
注:あなたはJavaEEのプロジェクトである場合には、溶接の作成に関連するすべてはあなたのコンテナによって管理されています。