我设置和@Around
方面在后台线程上运行方法,它看起来像这样
@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
的方法,但在ClassCastException
jp.proceed()
E/TEST (20943): java.lang.ClassCastException: java.lang.String cannot be cast to org.aspectj.lang.JoinPoint
有趣的是,如果我没有使用某个帖子,那么这个电话就好了。如何让它在线程上运行?
如果重要,我会在this plugin使用android上的aspectj。
编辑:这是失败的代码
// 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 :(得分: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 {}
驱动程序应用程序:
如您所见,一种方法由注释标记,另一种方法不标记。
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();
}
}
没有AspectJ的控制台输出:
18:21:09 - synchronous call
18:21:09 - asynchronous call
18:21:09 - synchronous call
18:21:09 - asynchronous call
如您所见,这些方法按照调用它们的顺序记录,并且所有方法都具有相同的时间戳。
Aspect在自己的线程中异步运行标记的方法:
这几乎就是你的方面代码,但我插入了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
正如您在此处所见,两个异步调用(背景任务)在同步调用后2秒打印。