Создайте пользовательскую аннотацию Java для изменения метода

Я хочу создать аннотацию, чтобы весной сделать метод асинхронным, как @Async, но для Android. Я проверил процессор аннотаций Java, но он не позволяет изменять существующий класс (мы можем только создать новый класс). Я не хочу использовать библиотеку androidannotation, потому что я также хочу научиться создавать свои собственные аннотации

Я видел, что lombok позволяет изменять класс (добавлять методы получения и установки), и мы можем добавлять собственные аннотации ( https://binkley.blogspot.fr/2014/12/writing-your-own-lombok-annotation.html).

Но у меня проблемы с модификацией этого примера, чтобы создать асинхронную задачу и ввести код метода.

Спасибо за помощь

@AsyncTask
void doSomething(int a){
    Log.d("here");
}

->

void doSomething(int a){
    new android.os.AsyncTask<Void, Void, Void>() {
        @Override
        protected Void doInBackground( Void... voids ) {
            Log.d("here");
            return null;
        }
    }.execute();
}

1 ответ

Сначала мы определяем аннотацию:

@Documented
@Retention(RUNTIME)
@Target(METHOD)
public @interface AsyncTask {
}

Тогда мы используем cglib создать асинхронную логику для @AsyncTask метод:

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;

public class AsyncTaskHandler {
  @SuppressWarnings("unchecked")
  public static <T> T handle(T origin) {
    // collect async methods
    List<Method> asyncMethods = Arrays.stream(origin.getClass().getMethods())
        .filter(m -> m.getAnnotation(AsyncTask.class) != null)
        .collect(Collectors.toList());
    // if no async method, return itself
    if (asyncMethods.isEmpty()) {
      return origin;
    }
    return (T) Enhancer.create(origin.getClass(), (MethodInterceptor) (obj, method, args, proxy) -> {
      // if asyn, wrapped in your async code, here I simply create a new thread
      if (asyncMethods.contains(method)) {
        // your async logic
        new Thread(() -> {
          try {
            proxy.invoke(origin, args);
          } catch (Throwable e) {
            e.printStackTrace();
          }
        }).start();
        return null;
      }
      return proxy.invoke(origin, args);
    });
  }
}

Давайте проверим наш код.

public class SomeObject {

  public static void main(String[] args) {
    SomeObject so = SomeObject.create();
    so.syncDo("1");
    so.asyncDo("2");
    so.syncDo("3");
    so.asyncDo("4");
  }

  public static SomeObject create() {
    return AsyncTaskHandler.handle(new SomeObject());
  }

  protected SomeObject() {}

  @AsyncTask
  public void asyncDo(String who) {
    System.out.println(who + "\tThread: " + Thread.currentThread());
  }

  public void syncDo(String who) {
    System.out.println(who + "\tThread: " + Thread.currentThread());
  }
}

и вывод:

1   Thread: Thread[main,5,main]
3   Thread: Thread[main,5,main]
2   Thread: Thread[Thread-0,5,main]
5   Thread: Thread[Thread-1,5,main]
Другие вопросы по тегам