用于调用具有特定注释的 class 成员上的方法的 AspectJ 切入点模式
AspectJ pointcut pattern for calling to the method on class member with specific annotation
我对 AspectJ 没有任何经验,但最近我有一个任务要实现,并且我阅读了一些 AspectJ 教程,所以我认为 AspectJ 可以成为我的解决方案。
任务如下:
我有一个 class A 和一些方法 b() 并且此 class 的对象作为字段包含在其他 classes 中。
我想用一些注释 @C 来注释这些字段,并在每次我在类型为 A 和注释 @C 的字段上调用方法 b() 时获取此注释值。
简化代码:
class A{
field1;
field2;
field3;
void b(String[] fieldsToIgnore){
doSomething with fields 1,2,3 (excluding fields from fieldsToIgnore array)
}
}
class B{
@C(value="field1,field2")
A fieldA;
}
//Here when I want to weaver my aspect - before I call to method b() on fieldA with annotation @C - I want to get annotation value and to pass it as an argument to method b()
new B.fieldA.b()
请帮我写出正确的切入点给我建议。我也不太明白如何将数据从我的 advise 方法传输到我的方法 b() - 这可能吗?
感谢任何帮助 - 即使您只是告诉 mt "No, it's not possible" - 这会节省我很多时间和精力:)
实际上,如果您已经在大量使用反射 - 这不是不重构代码的借口,顺便说一句 - 并且希望继续这样做,实际上您并不真的需要 AspectJ 来使混乱变得均匀更差。你可以这样做:
用于反射字段访问的助手class:
package de.scrum_master.app;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
public class FieldHelper {
public static Field getField(Class<?> clazz, String fieldName) {
Field field;
try {
field = clazz.getDeclaredField(fieldName);
} catch (NoSuchFieldException | SecurityException e) {
throw new RuntimeException("Reflection problem", e);
}
field.setAccessible(true);
return field;
}
public static Field[] getFields(Class<?> clazz) {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields)
field.setAccessible(true);
return fields;
}
public static List<String> extractIgnoredFieldsList(Class<?> clazz, String fieldName) {
return Arrays.asList(
getField(clazz, fieldName)
.getAnnotation(IgnoreFields.class)
.fieldNames()
);
}
}
标记注释:
package de.scrum_master.app;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface IgnoreFields {
public String[] fieldNames();
}
Class 调用方法:
package de.scrum_master.app;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.List;
import static de.scrum_master.app.FieldHelper.*;
public class A {
int number = 11;
String text = "Hi there!";
Date date = new Date();
String optionalText = "I am not really always needed";
int optionalNumber = 123;
public void doSomething(List<String> ignoredFields) {
for (Field field : getFields(this.getClass())) {
if (!ignoredFields.contains(field.getName())) {
try {
System.out.println(field.getName() + " = " + field.get(this));
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException("Reflection problem", e);
}
}
}
}
}
Class 带注释的成员字段:
package de.scrum_master.app;
import static de.scrum_master.app.FieldHelper.*;
public class B {
@IgnoreFields(fieldNames = { "optionalText", "optionalNumber" })
A noOptionalsA = new A();
@IgnoreFields(fieldNames = { "text", "number", "date" })
A onlyOptionalsA = new A();
public static void main(String[] args) {
B b = new B();
b.noOptionalsA.doSomething(extractIgnoredFieldsList(b.getClass(), "noOptionalsA"));
System.out.println("----------------------------------------");
b.onlyOptionalsA.doSomething(extractIgnoredFieldsList(b.getClass(), "onlyOptionalsA"));
}
}
控制台日志:
number = 11
text = Hi there!
date = Wed Dec 27 18:54:44 ICT 2017
----------------------------------------
optionalText = I am not really always needed
optionalNumber = 123
如果您不明白这里发生了什么,或者您仍然坚持使用 AspectJ 解决方案,请告诉我,我会解释 and/or 提供额外的方面代码。
我对 AspectJ 没有任何经验,但最近我有一个任务要实现,并且我阅读了一些 AspectJ 教程,所以我认为 AspectJ 可以成为我的解决方案。
任务如下: 我有一个 class A 和一些方法 b() 并且此 class 的对象作为字段包含在其他 classes 中。 我想用一些注释 @C 来注释这些字段,并在每次我在类型为 A 和注释 @C 的字段上调用方法 b() 时获取此注释值。
简化代码:
class A{
field1;
field2;
field3;
void b(String[] fieldsToIgnore){
doSomething with fields 1,2,3 (excluding fields from fieldsToIgnore array)
}
}
class B{
@C(value="field1,field2")
A fieldA;
}
//Here when I want to weaver my aspect - before I call to method b() on fieldA with annotation @C - I want to get annotation value and to pass it as an argument to method b()
new B.fieldA.b()
请帮我写出正确的切入点给我建议。我也不太明白如何将数据从我的 advise 方法传输到我的方法 b() - 这可能吗?
感谢任何帮助 - 即使您只是告诉 mt "No, it's not possible" - 这会节省我很多时间和精力:)
实际上,如果您已经在大量使用反射 - 这不是不重构代码的借口,顺便说一句 - 并且希望继续这样做,实际上您并不真的需要 AspectJ 来使混乱变得均匀更差。你可以这样做:
用于反射字段访问的助手class:
package de.scrum_master.app;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
public class FieldHelper {
public static Field getField(Class<?> clazz, String fieldName) {
Field field;
try {
field = clazz.getDeclaredField(fieldName);
} catch (NoSuchFieldException | SecurityException e) {
throw new RuntimeException("Reflection problem", e);
}
field.setAccessible(true);
return field;
}
public static Field[] getFields(Class<?> clazz) {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields)
field.setAccessible(true);
return fields;
}
public static List<String> extractIgnoredFieldsList(Class<?> clazz, String fieldName) {
return Arrays.asList(
getField(clazz, fieldName)
.getAnnotation(IgnoreFields.class)
.fieldNames()
);
}
}
标记注释:
package de.scrum_master.app;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface IgnoreFields {
public String[] fieldNames();
}
Class 调用方法:
package de.scrum_master.app;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.List;
import static de.scrum_master.app.FieldHelper.*;
public class A {
int number = 11;
String text = "Hi there!";
Date date = new Date();
String optionalText = "I am not really always needed";
int optionalNumber = 123;
public void doSomething(List<String> ignoredFields) {
for (Field field : getFields(this.getClass())) {
if (!ignoredFields.contains(field.getName())) {
try {
System.out.println(field.getName() + " = " + field.get(this));
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException("Reflection problem", e);
}
}
}
}
}
Class 带注释的成员字段:
package de.scrum_master.app;
import static de.scrum_master.app.FieldHelper.*;
public class B {
@IgnoreFields(fieldNames = { "optionalText", "optionalNumber" })
A noOptionalsA = new A();
@IgnoreFields(fieldNames = { "text", "number", "date" })
A onlyOptionalsA = new A();
public static void main(String[] args) {
B b = new B();
b.noOptionalsA.doSomething(extractIgnoredFieldsList(b.getClass(), "noOptionalsA"));
System.out.println("----------------------------------------");
b.onlyOptionalsA.doSomething(extractIgnoredFieldsList(b.getClass(), "onlyOptionalsA"));
}
}
控制台日志:
number = 11
text = Hi there!
date = Wed Dec 27 18:54:44 ICT 2017
----------------------------------------
optionalText = I am not really always needed
optionalNumber = 123
如果您不明白这里发生了什么,或者您仍然坚持使用 AspectJ 解决方案,请告诉我,我会解释 and/or 提供额外的方面代码。