2017-11-28 6 views
1

봄에는 @Async와 같은 비동기식 메소드를 만들기 위해 주석을 만들고 싶습니다. Java의 주석 프로세서를 검사했지만 기존 클래스를 수정할 수 없습니다 (새 클래스 만 만들 수 있음). 자신의 주석을 만드는 방법을 배우기 때문에 androidannotation 라이브러리를 사용하고 싶지 않습니다.메소드를 수정하기 위해 사용자 정의 자바 주석 만들기

I 롬 보크가 클래스를 수정하는 것을 허용하고 (getter와 setter를 추가 할 수 있습니다) 사용자 정의 주석을 추가 할 수 있습니다. (https://binkley.blogspot.fr/2014/12/writing-your-own-lombok-annotation.html)

그러나이 예제를 수정하여 asynctask를 작성하고 메소드의 코드를 삽입하는 데 어려움이 있습니다. 우리가 @AsyncTask에 대한 asyn 로직을 만들 수 cglib을 사용하여 다음

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

:>

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

수정 클래스가 위험 모든 JVM의 유지가 필요합니다. 생성 된 클래스를 생성하거나 프록시를 사용하는 것이 어떻습니까? –

답변

0

첫째, 우리는 주석을 정의 -

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

여러분의 도움에 감사드립니다 방법 :

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] 
+0

안녕하십니까. 답장을 보내 주셔서 감사합니다. 그러나 성능 향상을 위해 런타임 중이 아닌 컴파일 중 코드를 수정하여 주석을 원했습니다. 그래서이 메커니즘을 사용하는 롬복에 관심이 있습니다. – kazouz

+0

@kazouz Lombok은 새 바이트 코드를 생성하도록 AST를 수정합니다. 유지하기가 어렵습니다. 존재하는 코드를 변경하는 것이 아니라 주석 처리에 새로운 클래스 파일을 생성합니다. –