Javaの達人、
私はannotations
が初めてなので、これをあまり検索していません。
メソッド呼び出しをintercept
するCustom Annotation
を実装したいと思います。非常に基本的なものから始めるには、メソッド名とパラメーターを出力するだけで、logger
ステートメントを回避できます。
このようなサンプル呼び出し:
public MyAppObject findMyAppObjectById(Long id) throws MyCustomException {
log.debug("in findMyAppObjectById(" + id + ")");
//....
}
以下に変換できます:
@LogMethodCall(Logger.DEBUG)
public MyAppObject findMyAppObjectById(Long id) throws MyCustomException {
//....
}
これについてのヒントを得ることができますか?
私のコメントの回答に基づいて、あなたはこれを注釈だけで行うことはできません。もちろん、アノテーションを作成し、それを検出して反射するコードを作成し、コードを実行できますが、呼び出す前にparser
メソッドを呼び出す必要があるため、コードをあまり変更しませんあなたのメソッドと私はあなたが各呼び出しの前にパーサーメソッドを呼び出す必要があるので、あまりあなたを助けないと思います。
言及した動作(自動呼び出し)が必要な場合、Spring(プレーンJava)やAspectJ(AspectJコード)などのAOPフレームワークと注釈を組み合わせる必要があります。その後、ポイントカットを設定し、このポイントに到達するたびに、いくつかのコードが実行される場合があります。メソッド実行の前後にコードを実行するように構成できます。
最初のシナリオで十分であれば、次のようなことができます。
ロガー:enum
public enum Logger {
INFO,
DEBUG;
}
LogMethodCall:アノテーション
import Java.lang.annotation.ElementType;
import Java.lang.annotation.Retention;
import Java.lang.annotation.RetentionPolicy;
import Java.lang.annotation.Target;
@Retention( RetentionPolicy.RUNTIME ) // the annotation will be available during runtime
@Target( ElementType.METHOD ) // this can just used in methods
public @interface LogMethodCall {
Logger logLevel() default Logger.INFO;
}
Person:注釈付きクラス
public class Person {
// will use the default log level (INFO)
@LogMethodCall
public void foo( int a ) {
System.out.println( "foo! " + a );
}
@LogMethodCall( logLevel = Logger.DEBUG )
public void bar( int b ) {
System.out.println( "bar! " + b );
}
}
Utils:log静的メソッドを使用したクラス(これは「解析」を実行します)
public class Utils {
public static void log( Object o, String methodName ) {
// gets the object class
Class klass = o.getClass();
// iterate over its methods
for ( Method m : klass.getMethods() ) {
// verify if the method is the wanted one
if ( m.getName().equals( methodName ) ) {
// yes, it is
// so, iterate over its annotations
for ( Annotation a : m.getAnnotations() ) {
// verify if it is a LogMethodCall annotation
if ( a instanceof LogMethodCall ) {
// yes, it is
// so, cast it
LogMethodCall lmc = ( LogMethodCall ) a;
// verify the log level
switch ( lmc.logLevel() ) {
case INFO:
System.out.println( "performing info log for \"" + m.getName() + "\" method" );
break;
case DEBUG:
System.out.println( "performing debug log for \"" + m.getName() + "\" method" );
break;
}
}
}
// method encountered, so the loop can be break
break;
}
}
}
}
AnnotationProcessing:注釈処理をテストするためのコードを持つクラス
public class AnnotationProcessing {
public static void main(String[] args) {
Person p = new Person();
Utils.log( p, "foo" );
p.foo( 2 );
Utils.log( p, "bar" );
p.bar( 3 );
}
}
もちろん、ニーズに合わせてコードを改善する必要があります。これは単なる出発点です。
注釈の詳細:
AOPの詳細:
すでに提案したように、AOPと注釈が最適なオプションです。 jcabi-aspects (私は開発者です)から既製のメカニズムを使用することをお勧めします。
@Loggable(Loggable.DEBUG)
public String load(URL url) {
return url.openConnection().getContent();
}
すべてのメソッド呼び出しはSLF4Jに記録されます。