注記を使用したspringのaopで、メソッドで他のメソッドを呼び出すことができない(関数内部呼び出しでブロックできない)問題を解決します.
最近、プロジェクトにユーザーログを記録し、カスタム注釈を使用してaopブロックを行い、呼び出しクラスをブロックできる最初の方法を発見しました.方法で他の方法を呼び出すと、他の方法はブロックできません.クエリーを経て、aop自身の動的エージェントによるものであることがわかりました.以下、プロジェクトのコードを貼ります.
1、カスタム注記
2、springのaopコード
3、コントロール中の方法でブロックする
4、テスト、印刷結果を見る
メソッドで呼び出された2番目のメソッドはブロックされていないことがわかります.
理由:
このクラスを呼び出すと、エージェントオブジェクトが呼び出され、エージェントクラスの内部コードはほぼ次のようになります.
5、コードの修正
ApplicationContextを取得し、コンテナからオブジェクトを取得し、そのオブジェクトにエージェントオブジェクトがあればエージェントオブジェクトを取得できます.
6、テスト
2つ目の方法もブロックされた.
7、まとめ
Springはaopを使用して関数内部呼び出しを行うことをお勧めしません.呼び出した関数を別のクラスに書くことができます.しかし、これではコードが少し乱れてしまうので、私のプロジェクトで状況を見て、上の書き方が便利であれば、私はやはり上の方法で=.=
この问题は最初は私を困らせて、インターネットでこの问题を调べて大神解答があって、とても感谢して、同じく记录します.
1、カスタム注記
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogController {
String operationContent() default "";
}
2、springのaopコード
@Aspect
@Component
public class UserLogAspect {
@Pointcut("@annotation(com.jingli.creditchain.service.userlog.LogController)")
public void methodAspect() {
}
@SuppressWarnings("rawtypes")
@After("methodAspect()")
public void doAfter(JoinPoint joinPoint) {
try {
//
Object target = joinPoint.getTarget();
//
String methodName = joinPoint.getSignature().getName();
//
Class[] parameterTypes = ((MethodSignature)joinPoint.getSignature()).getMethod().getParameterTypes();
// method
Method method = target.getClass().getMethod(methodName, parameterTypes);
String content = method.getAnnotation(LogController.class).operationContent();
//
System.out.println("================="+content);
} catch (Exception e) {
e.printStackTrace();
}
}
}
3、コントロール中の方法でブロックする
@LogController(operationContent = "findApply")
@RequestMapping(path = "/list", method = RequestMethod.POST)
public List findApply(@RequestBody QueryInnerApplyVm query) {
// vm, ( )
QueryParam queryParam = queryInnerApplyVmToQueryParam(query);
return applyService.findApply(queryParam)
.stream()
.filter(Objects::nonNull)
.map(this::assignApplyVm)
.collect(Collectors.toList());
}
//
@LogController(operationContent = "queryInnerApplyVmToQueryParam")
public QueryParam queryInnerApplyVmToQueryParam(QueryInnerApplyVm vm) {
return new QueryParam();
}
4、テスト、印刷結果を見る
=================findApply
メソッドで呼び出された2番目のメソッドはブロックされていないことがわかります.
理由:
このクラスを呼び出すと、エージェントオブジェクトが呼び出され、エージェントクラスの内部コードはほぼ次のようになります.
private ApplyController applyController;
public List findApply(@RequestBody QueryInnerApplyVm query) {
// , , , ,
。 , , 。
QueryParam queryParam = applyController.queryInnerApplyVmToQueryParam(query);
}
5、コードの修正
ApplicationContextを取得し、コンテナからオブジェクトを取得し、そのオブジェクトにエージェントオブジェクトがあればエージェントオブジェクトを取得できます.
//
@Component
public class BeanUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(@NotNull ApplicationContext applicationContext){
BeanUtil.applicationContext = applicationContext;
}
public static T getBean(Class bean){
return applicationContext.getBean(bean);
}
}
@LogController(operationContent = "findApply")
@RequestMapping(path = "/list", method = RequestMethod.POST)
public List findApply(@RequestBody QueryInnerApplyVm query) {
QueryParam queryParam = BeanUtil.getBean(this.getClass()).queryInnerApplyVmToQueryParam(query);
}
6、テスト
=================queryInnerApplyVmToQueryParam
=================findApply
2つ目の方法もブロックされた.
7、まとめ
Springはaopを使用して関数内部呼び出しを行うことをお勧めしません.呼び出した関数を別のクラスに書くことができます.しかし、これではコードが少し乱れてしまうので、私のプロジェクトで状況を見て、上の書き方が便利であれば、私はやはり上の方法で=.=
この问题は最初は私を困らせて、インターネットでこの问题を调べて大神解答があって、とても感谢して、同じく记录します.