3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

めっちゃわかりやすいDIとAOPの仕組み(リフレクションで理解しよう)

3
Last updated at Posted at 2023-05-25

DIとAOPの仕組みを知るにはリフレクションを試すのがいいと思ってサンプルを準備してみました。

1. クラス名をもとにインスタンスを作れるか実験

まずはリフレクションを使うことでクラス情報をもとにインスタンスを制御できることを確認します。

package test;

public class ReflectionSampleService {
    public void execute() {
        System.out.println("メソッドが呼ばれた。");
    }
}
package test;

import java.lang.reflect.Method;

public class ReflectionDemo {
    public static void main(String[] args) throws Exception {
        // クラス名をもとにクラス情報を得る
        Class<?> clazz = Class.forName("test.ReflectionSampleService");
        // クラス情報をもとにメソッド情報が得る
        Method method = clazz.getMethod("execute");

        // クラス情報をもとにインスタンスを生成
        Object sampleService = clazz.getDeclaredConstructor().newInstance();
        // メソッド情報とインスタンスをもとに、インスタンスメソッドを実行する
        // 実質: sampleService.execute()
        method.invoke(sampleService);
    }
}
メソッドが呼ばれた。

2. メソッドが呼ばれたことを検知できるか実験

次に、インスタンスを制御できると、メソッドが呼ばれたことを検知して前後処理が仕込めることを確認します。

public interface SomeService {
    void someMethod();
}
public class SomeServiceImpl implements SomeService {
    @Override
    public void someMethod() {
        System.out.println("メソッドが呼ばれた。");
    }
}
public interface OtherService {
    void otherMethod();
}
public class OtherServiceImpl implements OtherService {
    @Override
    public void otherMethod() {
        System.out.println("メソッドが呼ばれた。");
    }    
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class AopInvocationHandler implements InvocationHandler {
    private final Object target;

    public AopInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(method.getName() + "() Before");
        Object result = method.invoke(target, args);
        System.out.println(method.getName() + "() After");
        return result;
    }
}
import java.lang.reflect.Proxy;

public class AopDemo {
    public static void main(String[] args) {
        SomeService someService = create(SomeService.class, new SomeServiceImpl());
        OtherService otherService = create(OtherService.class, new OtherServiceImpl());

        someService.someMethod();
        otherService.otherMethod();
    }

    public static <T> T create(Class<T> interfaceType, T target) {
        Class<?> targetClass = target.getClass();

        // チェックすべき
        // 1. interfaceTypeがインターフェースであること
        // 2. targetClassがインターフェースの実装であること

        Object proxy = Proxy.newProxyInstance(
                targetClass.getClassLoader(),
                new Class<?>[] { interfaceType },
                new AopInvocationHandler(target));

        return interfaceType.cast(proxy);
    }
}
someMethod() Before
メソッドが呼ばれた。
someMethod() After
otherMethod() Before
メソッドが呼ばれた。
otherMethod() After

3. まとめ

  1. DIにクラス情報を登録しておく(このページでは実験なし)
  2. 登録されたクラス情報をもとにインスタンスをつくる
  3. メソッドの実行をハンドリングし、呼ばれたメソッドの前後に処理を挟む

この2つのサンプルを確認によって、DIやAOPで使われるリフレクションの考え方が理解できると幸いです。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?