8

インターフェース:

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オブジェクトは宣言クラスのインスタンスではありません。
これは合理的です。

問題は、スプリングによって作成されたプロキシ オブジェクトのリフレクションを介してメソッドを呼び出す方法です (ターゲット オブジェクトから抽出されたメソッドがあり、スプリングによって作成されたプロキシのインスタンスがあります)

アスペクトが呼び出されないため、ターゲットで呼び出しを実行できません。

4

4 に答える 4

0

Java リフレクションが旅行を行うとは思わないので、 if() ポイントカット式を使用する必要があります

それを実装するには、別のブール引数 (invokeAOP という名前) を定義できますmanager。invokeAOP = true で呼び出すと、アスペクトが実行されます。そうしないと、アスペクトが省略されます。

于 2015-07-20T15:11:37.923 に答える