是否可以拦截方法调用和方法调用的方法的参数:AOP [英] Is it possible to intercept arguments of a method call and method inside which the method call is made : AOP

查看:26
本文介绍了是否可以拦截方法调用和方法调用的方法的参数:AOP的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 DAO,它有一些使用 org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate 查询数据库的方法.这些方法很少有某些方法参数,我想捕获从这些方法进行的数据库查询.我想编写一个 AOP 来捕获从这些方法进行的 SQL 查询以及参数的值.以下是进行 jdbc 查询的方法之一(我需要捕获):我的 DAO-

I have a DAO that has some methods that make queries to a database using org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate. Few of this methods have certain method arguments and I would like to capture database queries made from these methods. I would like to write an AOP that would capture the SQL queries made from these methods along with the value of the argument. Below is one of the methods(that I need to capture) that makes jdbc query: My DAO-

public List<Map<String, Object>> getData(RequestParameters requestParameter, Map<String, Column> columnMap) {
    Map<String, Object> params = new HashMap<>();
    StringBuilder finalQuery = new StringBuilder();
    finalQuery.append(getDataQuery(requestParameter, columnMap, params));
    return namedParameterJdbcTemplate.queryForList(finalQuery.toString(), params);

我需要一个 AOP 解决方案来捕获 finalQuerycolumnMap.这在 AOP 中甚至是可能的.您还有其他解决方案吗?

I need an AOP solution that would capture finalQuery and columnMap. Is that even possible in AOP. Do you have any other solutions?

我试图写下面的方面,但我只能捕获 finalQuery 而不是 columnMap

I tried to write below aspect but I am able to only capture finalQuery but not columnMap

@Pointcut("withincode(public * com.abc.xyz..*.*(com.abc.xyz.RequestParameters, java.util.Map))")
private void anyGetDataMethodSignature() {
    // pointcut
}

@Pointcut("(call(* org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations.query*(..)) && within(com.abc.xyz.services..*.*))")
public void anyJDBCOperations() {
}

@Before("anyJDBCOperations() && anyGetDataMethodSignature()")
public void log(JoinPoint jp) throws Throwable {
//......
}

提前致谢

推荐答案

好吧,只是为了让你明白什么是 MCVE 如果您愿意,提供一个是多么容易,我为您制作了一个.实际上,这是你的工作!下次请自己做.

Okay, just in order to make you understand what an MCVE is and how easy it is to provide one if you only want, I made one for you. Actually this was your job! Next time do it by yourself, please.

您不连贯的片段没有告诉我要导入哪些类、如何定义和初始化诸如 namedParameterJdbcTemplate 之类的变量、如何配置 Spring Boot 等等.所以我不得不做出有根据的猜测并创建虚拟类,以便重现您的情况并测试我自己的解决方案.未经测试的解决方案是 cr*p,所以首先是一个迫使我做这种猜测的问题.

Your incoherent snippets do not tell me which classes to import, how variables like namedParameterJdbcTemplate are defined and initialised, how your Spring Boot is configured and many more things. So I had to make educated guesses and create dummy classes just so as to recreate your situation and test my own solution. Untested solutions are cr*p and so is a question forcing me to do that kind of guesswork in the first place.

你想要实现的是虫洞模式,另见我的回答这里此处,均采用 AspectJ 原生语法.我为您准备的一种是基于注释的语法,我非常不喜欢,但无论出于何种原因,您似乎都喜欢这种语法.

What you want to implement is the wormhole pattern, see also my answers here and here, both in AspectJ native syntax. The one I prepared for you is in the annotation-based syntax I so dislike, but which you seem to prefer for whatever reason.

虚拟助手类:

package de.scrum_master.app;

public class RequestParameters {}

package de.scrum_master.app;

import java.util.List;
import java.util.Map;

public class DummyJdbcTemplate {
  public List<Map<String, Object>> queryForList(String string, Map<String, Object> params) {
    return null;
  }
}

package de.scrum_master.app;

public class Column {
  private String columnType;

  public Column(String columnType) {
    this.columnType = columnType;
  }

  @Override
  public String toString() {
    return "Column[columnType=" + columnType + "]";
  }
}

驱动程序应用:

package de.scrum_master.app;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Application {
  private DummyJdbcTemplate namedParameterJdbcTemplate = new DummyJdbcTemplate();

  public List<Map<String, Object>> getData(RequestParameters requestParameter, Map<String, Column> columnMap) {
    Map<String, Object> params = new HashMap<>();
    StringBuilder finalQuery = new StringBuilder();
    finalQuery.append(getDataQuery(requestParameter, columnMap, params));
    return namedParameterJdbcTemplate.queryForList(finalQuery.toString(), params);
  }

  public String getDataQuery(RequestParameters requestParameter, Map<String, Column> columnMap, Map<String, Object> params) {
    return "I am the final query";
  }

  public static void main(String[] args) {
    HashMap<String, Column> columnMap = new HashMap<>();
    columnMap.put("id", new Column("Long"));
    columnMap.put("name", new Column("VarChar"));
    columnMap.put("age", new Column("Int"));
    new Application().getData(new RequestParameters(), columnMap);
  }
}

实现虫洞模式的方面:

package de.scrum_master.aspect;

import java.util.Map;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import de.scrum_master.app.Column;

@Aspect
public class MyAspect {
  @Pointcut(
    "execution(public * de.scrum_master.app..*(..)) && " +
    "args(de.scrum_master.app.RequestParameters, columns)"
  )
  private void anyGetDataMethodSignature(Map<String, Column> columns) {}

  @Pointcut(
    "call(* de.scrum_master.app.DummyJdbcTemplate.query*(..)) && " +
    "args(query, ..)"
  )
  private void anyJDBCOperations(String query) {}

  @Before(
    "anyJDBCOperations(query) &&" +
    "cflow(anyGetDataMethodSignature(columns))"
  )
  public void log(JoinPoint thisJoinPoint, Map<String, Column> columns, String query) throws Throwable {
    System.out.println(thisJoinPoint);
    System.out.println("  columns = " + columns);
    System.out.println("  query = " + query);
  }
}

控制台日志:

call(List de.scrum_master.app.DummyJdbcTemplate.queryForList(String, Map))
  columns = {name=Column[columnType=VarChar], id=Column[columnType=Long], age=Column[columnType=Int]}
  query = I am the final query

现在,阿米特,为您的 SO 助手提供一个小例子,让他们不必在业余时间免费做自己的工作,这对您来说有什么困难?只需拿起并修复您自己的 MCVE 就会容易得多,而且绝对不会向您认为自己是的有经验的开发人员要求太多.这种权利感——这里的开发者没有什么比为自己创建一个运行示例更好的了,因为我太懒了."- 我就是不明白.你是谁?国王?

Now, Amit, what the heck was so difficult for you about providing a little example for your SO helpers' benefit, so they don't have to do your own job for free in their spare time? Just picking up and fixing your own MCVE would have been so much easier and definitely not asking too much of the experienced developer you seem to think you are. This sense of entitlement - "Developers here have nothing better to do than create a running example for themselves because I am too lazy." - I just don't get it. Who are you? A king?

这篇关于是否可以拦截方法调用和方法调用的方法的参数:AOP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆