AspectJ切入点模式,用于使用特定注释调用类成员上的方法

问题描述 投票:0回答:1

我对AspectJ没有任何经验,但最近我有任务要实现,我已经阅读了几个AspectJ教程,所以我认为AspectJ可以成为我的解决方案。

任务如下:我有一个类A和一些方法b(),这个类的对象作为字段包含在其他类中。我想用一些注释@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()

请帮我写一下正确的切入点给我建议。我也不太明白如何将数据从我的建议方法转移到我的方法b() - 它有可能吗?

将会感激任何帮助 - 即使你只是告诉“不,这是不可能的” - 它将节省我很多时间和神经:)

java annotations aspectj
1个回答
1
投票

实际上,如果你已经大量使用反射 - 这不是不重构代码的借口,BTW - 并希望继续这样做,实际上你并不真正需要AspectJ来使混乱更糟糕。你可以这样做:

用于反射现场访问的助手类:

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

具有被调用方法的类:

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

带注释成员字段的类:

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解决方案,请告诉我,我会解释和/或提供额外的方面代码。

© www.soinside.com 2019 - 2024. All rights reserved.