先来看代码:
[code="java"]@Controller
public class T1 implements MethodInterceptor {
private Object obj;
@Autowired
private SimpleAsyncTaskExecutor task;
public Object invoke(final MethodInvocation mi) throws Throwable {
task.execute(new Runnable(){
public void run() {
try {
obj = mi.proceed(); // 这里我需要把执行的结果传入到T1类,我定义了一个Object对象,可是值是传不出来的
} catch (Throwable e) {
e.printStackTrace();
}
}
});
return obj; // 刚才传的值这里要用
}
}[/code]
MethodInterceptor是我实现了spring中一个接口,关于aop的。
SimpleAsyncTaskExecutor是spring中的一个类,用于实现对并发的总数做限制的。
上面我写的有注释,内部类执行的值怎么才能传出来给T1类使用呢?
[b]问题补充:[/b]
@RednaxelaFX,非常感谢,按照你的方法,问题解决了:
[code="java"]@Controller
public class T1 implements MethodInterceptor {
@Autowired
private SimpleAsyncTaskExecutor executor;
public Object invoke(final MethodInvocation mi) throws Throwable {
FutureTask<Object> task = new FutureTask<Object>(new Callable<Object>() {
public Object call() {
try {
return mi.proceed();
} catch (Throwable e) {
return null;
}
}
});
executor.execute(task);
return task.get();
}
}[/code]
Java的匿名内部类的使用限制是它只能访问外围类中的final成员,但没关系,Java中final对引用类型的语义是“这个引用在初始化之后不能用于指向别的对象”,至于被指向的对象的状态怎么变它不关心。所以随便用什么容器都能够从匿名内部类中返回值:
[code="java"]interface IFoo {
void foo();
}
public class Test {
private final Object[] arr = new Object[1];
private void bar() {
(new IFoo() {
public void foo() {
arr[0] = "result";
}
}).foo();
}
public static void main(String[] args) throws Exception {
Test t = new Test();
t.bar();
System.out.println(t.arr[0]); // result
}
}[/code]
不过上面这段代码在多线程条件下明显很糟糕。不放心的话就用java.util.concurrent包里的容器:
[code="java"]import java.util.concurrent.*;
interface IFoo {
void foo();
}
public class Test {
private final BlockingQueue result = new ArrayBlockingQueue(1);
private void bar() {
(new IFoo() {
public void foo() {
try {
result.put("result");
} catch (Exception e) {
}
}
}).foo();
}
public static void main(String[] args) throws Exception {
Test t = new Test();
t.bar();
System.out.println(t.result.take()); // result
}
}[/code]
take会在还没有足够数据的时候block住。
不过要是能用Future系的接口就更好了。于是或许你不应用execute()方法,而应该用submit()方法来配合Callable接口使用。Runnable()本来就不适合用于返回值,Callable就是为了解决这个问题而出现的。类似这样
[code="java"]import java.util.concurrent.*;
@Controller
public class T1 implements MethodInterceptor {
@Autowired
private SimpleAsyncTaskExecutor executor;
public Object invoke(final MethodInvocation mi) throws Throwable {
FutureTask<Object> task = new FutureTask(new Callable<Object>() {
public Object call() {
return mi.proceed();
}
});
executor.sumbit(task);
Object result = null;
try {
result = task.get();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}[/code]
具体怎么用还得看你自己的需要了。很明显你没把所有代码贴出来,或许有些别的地方要注意的,呵呵~
呃,刚才敲代码的时候手滑了,new FutureTask后面忘了。不过其实都是的话写不写都一样,反正类型擦除之后也就是Object……Java编译器对泛型的警告直接无视就是了 :-p