インターフェース:
public interface Manager {
Object read(Long id);
}
このインターフェースを実装するクラス:
@Transactional
Public class ManagerImpl implements Manager {
@Override
public Object read(Long id) {
// Implementation here
}
}
ManagerImpl のアスペクト:
@Aspect
public class Interceptor {
@Pointcut("execution(public * manager.impl.*.*(..))")
public void executionAsManager() {
}
@Around("executionAsManager()")
public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
// Do some actions
return joinPoint.proceed();
}
}
コントローラ:
@RestController()
public class Controller {
@Autowired
private Manager manager;
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public Object read(@PathVariable Long id) {
return manager.read(id);
}
@RequestMapping(value = "reflection/{id}", method = RequestMethod.GET)
public Object readViaReflection(@PathVariable Long id) {
return ManagerImpl.class.getMethod("read", Long.class).invoke(manager, id);
}
}
そのため、Spring がコントローラー プロキシ内にマネージャー変数を挿入すると、作成されたプロキシが作成されます。
メソッドが直接呼び出された場合:
manager.read(1L)
アスペクトが呼び出されます。
ただし、このようにしようとすると(readViaReflectionを参照)
ManagerImpl.class.getMethod("read", Long.class).invoke(manager, 1L);
取得したjava.lang.reflect.InvocationTargetExceptionオブジェクトは宣言クラスのインスタンスではありません。
これは合理的です。
問題は、スプリングによって作成されたプロキシ オブジェクトのリフレクションを介してメソッドを呼び出す方法です (ターゲット オブジェクトから抽出されたメソッドがあり、スプリングによって作成されたプロキシのインスタンスがあります)。
アスペクトが呼び出されないため、ターゲットで呼び出しを実行できません。