2015-06-26 26 views
0

我設立和@Around方面運行在後臺線程的方法,它看起來像這樣ProceedingJoinPoint.proceed()失敗,並拋出ClassCastException當新的線程運行

@Aspect 
public class ThreadAspect {  
    @Around("call(@Background void *(..))") 
    public void runInBackground(final ProceedingJoinPoint jp) throws Throwable { 
     new Thread(new JPRunner(jp)).start(); 
    } 

    private static class JPRunner implements Runnable { 
     ... 
     @Override 
     public void run() { 
      try { 
       jp.proceed(); 
      } catch (Throwable e) { 
       Log.e("TEST", "ThreadAspect", e); 
      } 
     } 
    } 
} 

我所應用的@Background註釋一個方法,它接受String但它失敗,就行了ClassCastExceptionjp.proceed()

E/TEST (20943): java.lang.ClassCastException: java.lang.String cannot be cast to org.aspectj.lang.JoinPoint 

有趣的是,如果我沒有使用一個線程,調用似乎看透就好做了。我怎樣才能讓它在一個線程上運行?

如果問題很重要,我在Android上使用aspectj與this plugin

編輯:這是失敗的代碼

// Background.java 
package com.github.larvyde.ex.aspect; 

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.METHOD) 
public @interface Background {} 

// MainActivity.java 
package com.github.larvyde.ex.aspect; 

import android.os.Bundle; 
import android.util.Log; 

public class MainActivity extends android.support.v7.app.AppCompatActivity { 
    @Override 
    public void onCreate(Bundle saved) { 
     super.onCreate(saved); 

     Log.v("TEST", "calling runInBackground"); 
     runInBackground("run #1"); 
     Log.v("TEST", "calling runInBackground again"); 
     runInBackground("run #2"); 
    } 

    @Background 
    public void runInBackground(String str) { 
     Log.v("TEST", str); 
    } 
} 

// ThreadAspect.java 
package com.github.larvyde.ex.aspect; 

import org.aspectj.lang.ProceedingJoinPoint; 
import org.aspectj.lang.annotation.Around; 
import org.aspectj.lang.annotation.Aspect; 
import android.util.Log; 

@Aspect 
public class ThreadAspect { 
    @Around("call(@Background void *(..))") 
    public void runInBackground(ProceedingJoinPoint jp) throws Throwable { 
     new Thread(new JPRunner(jp)).start(); 
    } 

    private static class JPRunner implements Runnable { 
     private final ProceedingJoinPoint jp; 

     public JPRunner(ProceedingJoinPoint jp) { 
      this.jp = jp; 
     } 

     @Override 
     public void run() { 
      try { 
       jp.proceed(); 
      } catch (Throwable e) { 
       Log.e("TEST", "ThreadAspect", e); 
      } 
     } 
    } 
} 

日誌

$ adb logcat | egrep 'TEST|AndroidRuntime' 
V/TEST (21315): calling runInBackground 
V/TEST (21315): calling runInBackground again 
E/TEST (21315): ThreadAspect 
E/TEST (21315): java.lang.ClassCastException: java.lang.String cannot be cast to org.aspectj.lang.JoinPoint 
E/TEST (21315): at com.github.larvyde.ex.aspect.MainActivity$AjcClosure1.run(MainActivity.java:1) 
E/TEST (21315): at org.aspectj.runtime.reflect.JoinPointImpl.proceed(JoinPointImpl.java:149) 
E/TEST (21315): at com.github.larvyde.ex.aspect.ThreadAspect$JPRunner.run(ThreadAspect.java:25) 
E/TEST (21315): at java.lang.Thread.run(Thread.java:818) 
E/TEST (21315): ThreadAspect 
E/TEST (21315): java.lang.ClassCastException: java.lang.String cannot be cast to org.aspectj.lang.JoinPoint 
E/TEST (21315): at com.github.larvyde.ex.aspect.MainActivity$AjcClosure3.run(MainActivity.java:1) 
E/TEST (21315): at org.aspectj.runtime.reflect.JoinPointImpl.proceed(JoinPointImpl.java:149) 
E/TEST (21315): at com.github.larvyde.ex.aspect.ThreadAspect$JPRunner.run(ThreadAspect.java:25) 
E/TEST (21315): at java.lang.Thread.run(Thread.java:818) 

回答

0

對於我這個工作得很好,也許你的實際代碼是從你這裏張貼或你省略了一個不同索姆重要信息。看看我的單機例如:

標記註釋:

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.METHOD) 
public @interface Background {} 

驅動程序:

正如你所看到的,一種方法是由註釋標記,另一種是不。沒有AspectJ的

package de.scrum_master.app; 

import java.text.DateFormat; 
import java.text.SimpleDateFormat; 
import java.util.Calendar; 

public class Application { 
    static final DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); 

    public static void foreground() { 
     System.out.println(
      dateFormat.format(Calendar.getInstance().getTime()) + 
      " - synchronous call" 
     ); 
    } 

    @Background 
    public static void background() { 
     System.out.println(
      dateFormat.format(Calendar.getInstance().getTime()) + 
      " - asynchronous call" 
     ); 
    } 

    public static void main(String[] args) { 
     foreground(); 
     background(); 
     foreground(); 
     background(); 
    } 
} 

控制檯輸出:

18:21:09 - synchronous call 
18:21:09 - asynchronous call 
18:21:09 - synchronous call 
18:21:09 - asynchronous call 

正如你所看到的,這些方法都記錄在它們被調用的順序,並都具有相同的時間戳。

看點運轉異步標註在自己的線程方法:

這是相當多的方面的代碼,但我插入2秒的等待時間,以證明@Background效果。

package de.scrum_master.aspect; 

import org.aspectj.lang.ProceedingJoinPoint; 
import org.aspectj.lang.annotation.Around; 
import org.aspectj.lang.annotation.Aspect; 

@Aspect 
public class ThreadAspect { 
    @Around("call(@de.scrum_master.app.Background void *(..))") 
    public void runInBackground(final ProceedingJoinPoint jp) throws Throwable { 
     new Thread(new JPRunner(jp)).start(); 
    } 

    private static class JPRunner implements Runnable { 
     ProceedingJoinPoint jp; 
     JPRunner(ProceedingJoinPoint jp) { this.jp = jp; } 

     @Override public void run() { 
      try { Thread.sleep(2000); jp.proceed(); } 
      catch (Throwable e) { e.printStackTrace(); } 
     } 
    } 
} 

控制檯輸出使用AspectJ:

18:23:21 - synchronous call 
18:23:21 - synchronous call 
18:23:23 - asynchronous call 
18:23:23 - asynchronous call 

正如你可以在這裏看到,無論是異步調用(backgound任務)的同步後,那些打印2秒。

+0

不,它幾乎是從我的代碼複製粘貼。嗯,我看你測試它在普通的Java,所以我想這可能是一個問題與我使用的android aspectj插件... – larvyde

+0

我不這麼認爲。請提供[SSCCE](http://sscce.org/),以便使問題可以重現並證明相反。如果我能重現它,我可以幫助你。 – kriegaex

+0

在問題中增加了完整的代碼。 – larvyde

相關問題