是否可以拦截方法调用的参数和进行方法调用的方法:AOP

时间:2018-05-27 11:48:14

标签: spring-boot aop aspect

我有一个DAO,它有一些使用org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate对数据库进行查询的方法。这些方法中很少有一些方法参数,我想捕获这些方法产生的数据库查询。我想编写一个AOP,它将捕获从这些方法生成的SQL查询以及参数的值。下面是使jdbc查询的方法之一(我需要捕获): 我的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);

我需要一个能够捕获finalQuerycolumnMap的AOP解决方案。 这在AOP中是否可行。你有其他解决方案吗?

我尝试写下面的方面,但我只能抓取finalQuery而不是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 {
//......
}

先谢谢

1 个答案:

答案 0 :(得分:0)

好的,只是为了让您了解MCVE是什么以及如果您只想要提供一个是多么容易,我为您制作了一个。实际上这是 你的工作! 下次请自己做。

您的不连贯片段不会告诉我要导入哪些类,如何定义和初始化namedParameterJdbcTemplate等变量,如何配置Spring Boot以及更多内容。因此,我必须进行有根据的猜测并创建虚拟课程,以便重新创建您的情况并测试我自己的解决方案。未经测试的解决方案是cr * p,所以这是一个迫使我首先做出这种猜测的问题。

您要实现的是虫洞模式,另请参阅我的答案herehere,两者都是AspectJ原生语法。我为你准备的那个是基于注释的语法我不喜欢,但你似乎不管出于什么原因。

虚拟助手类:

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

现在,阿米特,你为你的助手提供一个小例子真是太困难了。好处,所以他们不必在业余时间免费做自己的工作?只需拿起并修复自己的MCVE就会变得如此简单,绝对不会过多地询问您认为自己的经验丰富的开发人员。这种权利感 - &#34;这里的开发人员没有比为自己创建一个运行示例更好的了,因为我太懒了。&#34; - 我只是不明白。你是谁?国王?