Is it possible to intercept arguments of a method call and method inside which the method call is made : AOP

坚强是说给别人听的谎言 提交于 2019-12-13 17:57:46

问题


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);

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

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 {
//......
}

Thanks in Advance


回答1:


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.

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.

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.

Dummy helper classes:

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 + "]";
  }
}

Driver application:

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);
  }
}

Aspect implementing wormhole pattern:

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);
  }
}

Console log:

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

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?



来源:https://stackoverflow.com/questions/50551816/is-it-possible-to-intercept-arguments-of-a-method-call-and-method-inside-which-t

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!