使用 AspectJ 更改 object 属性
Use AspectJ to change object properties
是否可以拦截 object 方法调用并在那一刻修改那些 object 属性?
到目前为止我有什么
@Pointcut("execution(* java.net.HttpURLConnection.setRequestProperty(..))")
public void connectMethodCall() {
}
@Around("connectMethodCall()")
public Object onGetUrlConnection(ProceedingJoinPoint pjp) throws Throwable {
HttpURLConnection connection = (HttpURLConnection) pjp.proceed();
connection.setRequestProperty("header key", "header value");
return pjp.proceed();
}
我想在此示例中将连接 headers 和 return object 设置为执行点。编织是在编译时完成的。我尝试在此之后记录 headers 但没有 headers 我在@Around 建议中设置的。也不会抛出任何错误。
我已经做到了
@Pointcut("call(* java.net.URL.openConnection())")
public void connectMethodCall() {
}
@Around("connectMethodCall()")
public Object onGetUrlConnection(ProceedingJoinPoint pjp) throws Throwable {
HttpURLConnection connection = (HttpURLConnection) pjp.proceed();
connection.setRequestProperty("From", "user@example.com");
return connection;
}
并在此处使用它来设置 headers
public static void main(String[] args) {
HttpURLConnection urlConnection;
String result;
try {
urlConnection = (HttpURLConnection) (new URL("http://www.google.com").openConnection());
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.setRequestMethod("POST");
urlConnection.setConnectTimeout(10000);
urlConnection.connect();
OutputStream outputStream = urlConnection.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8));
writer.write("test");
writer.close();
outputStream.close();
int responseCode = urlConnection.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
//Read
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), StandardCharsets.UTF_8));
String line;
StringBuilder sb = new StringBuilder();
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
bufferedReader.close();
result = sb.toString();
} else {
result = "false : " + responseCode;
}
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
相关代码的问题是我截获了 returns void 和 pjp.proceed() 实际上 returns null 的方法调用。 (仍然不确定是否有办法从 void 方法切入点中挖掘出调用 object?)。理想情况下我会拦截 urlConnection.connect();并从切入点获取 urlConnection object。有办法吗?
关于如何获取 target 对象实例的后续问题的答案很简单,如果我理解正确的话:只需使用 target()
参数绑定。快速浏览 AspectJ documentation would have showed you that, e.g. the part about pointcut parameters。我相信这比在这里提问要容易得多,也更省时(也考虑到必须等待关于 SO 的答案)。但无论如何,这是开发人员互相帮助的地方。所以我们开始吧:
尽管您的 MVCE 示例代码没有对 Google API 做任何有意义的事情,我们只添加一行诊断输出以验证方面确实添加了一个请求参数:
// (...)
urlConnection.connect();
// Just in order to check if the property has indeed been set in the aspect
System.out.println(urlConnection.getRequestProperty("From"));
OutputStream outputStream = urlConnection.getOutputStream();
// (...)
那就用这个方面:
package de.scrum_master.aspect;
import java.net.HttpURLConnection;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class MyAspect {
@Pointcut("call(* java.net.HttpURLConnection.connect()) && target(connection)")
public void connectMethodCall(HttpURLConnection connection) {}
@Around("connectMethodCall(connection)")
public Object onGetUrlConnection(ProceedingJoinPoint pjp, HttpURLConnection connection) throws Throwable {
connection.setRequestProperty("From", "user@example.com");
return pjp.proceed();
}
}
或者更紧凑一点,如果你不需要重复使用点,因为你只在一个建议中使用它:
@Aspect
public class MyAspect {
@Around("call(* java.net.HttpURLConnection.connect()) && target(connection)")
public Object onGetUrlConnection(ProceedingJoinPoint pjp, HttpURLConnection connection) throws Throwable {
connection.setRequestProperty("From", "user@example.com");
return pjp.proceed();
}
}
控制台日志为:
user@example.com
false : 405
是否可以拦截 object 方法调用并在那一刻修改那些 object 属性?
到目前为止我有什么
@Pointcut("execution(* java.net.HttpURLConnection.setRequestProperty(..))")
public void connectMethodCall() {
}
@Around("connectMethodCall()")
public Object onGetUrlConnection(ProceedingJoinPoint pjp) throws Throwable {
HttpURLConnection connection = (HttpURLConnection) pjp.proceed();
connection.setRequestProperty("header key", "header value");
return pjp.proceed();
}
我想在此示例中将连接 headers 和 return object 设置为执行点。编织是在编译时完成的。我尝试在此之后记录 headers 但没有 headers 我在@Around 建议中设置的。也不会抛出任何错误。
我已经做到了
@Pointcut("call(* java.net.URL.openConnection())")
public void connectMethodCall() {
}
@Around("connectMethodCall()")
public Object onGetUrlConnection(ProceedingJoinPoint pjp) throws Throwable {
HttpURLConnection connection = (HttpURLConnection) pjp.proceed();
connection.setRequestProperty("From", "user@example.com");
return connection;
}
并在此处使用它来设置 headers
public static void main(String[] args) {
HttpURLConnection urlConnection;
String result;
try {
urlConnection = (HttpURLConnection) (new URL("http://www.google.com").openConnection());
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.setRequestMethod("POST");
urlConnection.setConnectTimeout(10000);
urlConnection.connect();
OutputStream outputStream = urlConnection.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8));
writer.write("test");
writer.close();
outputStream.close();
int responseCode = urlConnection.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
//Read
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), StandardCharsets.UTF_8));
String line;
StringBuilder sb = new StringBuilder();
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
bufferedReader.close();
result = sb.toString();
} else {
result = "false : " + responseCode;
}
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
相关代码的问题是我截获了 returns void 和 pjp.proceed() 实际上 returns null 的方法调用。 (仍然不确定是否有办法从 void 方法切入点中挖掘出调用 object?)。理想情况下我会拦截 urlConnection.connect();并从切入点获取 urlConnection object。有办法吗?
关于如何获取 target 对象实例的后续问题的答案很简单,如果我理解正确的话:只需使用 target()
参数绑定。快速浏览 AspectJ documentation would have showed you that, e.g. the part about pointcut parameters。我相信这比在这里提问要容易得多,也更省时(也考虑到必须等待关于 SO 的答案)。但无论如何,这是开发人员互相帮助的地方。所以我们开始吧:
尽管您的 MVCE 示例代码没有对 Google API 做任何有意义的事情,我们只添加一行诊断输出以验证方面确实添加了一个请求参数:
// (...)
urlConnection.connect();
// Just in order to check if the property has indeed been set in the aspect
System.out.println(urlConnection.getRequestProperty("From"));
OutputStream outputStream = urlConnection.getOutputStream();
// (...)
那就用这个方面:
package de.scrum_master.aspect;
import java.net.HttpURLConnection;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class MyAspect {
@Pointcut("call(* java.net.HttpURLConnection.connect()) && target(connection)")
public void connectMethodCall(HttpURLConnection connection) {}
@Around("connectMethodCall(connection)")
public Object onGetUrlConnection(ProceedingJoinPoint pjp, HttpURLConnection connection) throws Throwable {
connection.setRequestProperty("From", "user@example.com");
return pjp.proceed();
}
}
或者更紧凑一点,如果你不需要重复使用点,因为你只在一个建议中使用它:
@Aspect
public class MyAspect {
@Around("call(* java.net.HttpURLConnection.connect()) && target(connection)")
public Object onGetUrlConnection(ProceedingJoinPoint pjp, HttpURLConnection connection) throws Throwable {
connection.setRequestProperty("From", "user@example.com");
return pjp.proceed();
}
}
控制台日志为:
user@example.com
false : 405