从任务

时间:2019-08-21 11:49:36

标签: java spring asynchronous-method-call

我有以下类(简化)可以使用Java和Spring工具箱实现异步方法调用。我需要添加一些在异步方法调用之前和之后执行的逻辑。

可通话。如果可以访问数据,我可以把我需要的逻辑放在这里。

public class ContextAwareCallable<T> implements Callable<T> {

    private Callable<T> task;
    private MyContext context;

    public ContextAwareCallable(Callable<T> task, MyContext context) {
        this.task = task;
        this.context = context;
    }

    @Override
    public T call() throws Exception {

              return task.call();
        }
}

这是执行程序,其中调用了任务。

public class ContextAwarePoolExecutor extends ThreadPoolTaskExecutor {

    private static final long serialVersionUID = 1L;

    @Override
    public <T> Future<T> submit(Callable<T> task) {
        return super.submit(new ContextAwareCallable<T>(task, myContext));
    }

这是配置程序。初始化执行程序。据我了解,我可以将TaskDecorator放在这里,儿子,我可以在里面做我需要的逻辑。不过,我仍然需要无法从TaskDecorator内部访问的方法中的数据。

@EnableAsync
@Configuration
public class MyAsyncPoolConfig implements AsyncConfigurer {

    @Override
    @Bean("DefaultAsyncTaskExecutor")
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(0);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(10);
        executor.setThreadNamePrefix("myPrefix");
        executor.initialize();
        return executor;

    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new MyAsyncUncaughtExceptionHandler();
    }

}

异步方法本身。

    @Service("TESTCOMPONENT_ASYNC_SERVICE_METHOD_CALL")
    @Async("TESTCOMPONENT_ASYNCTESTER_ASYNC_POOL")
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Throwable.class)

    public Future<AsyncCallMethodOutput> asyncMethodCall(AsyncCallMethodInput methodInput) throws MyException {
   // actual thing done here
}

这是调用异步方法的地方。

AsyncServiceExampleService asyncServiceExample = SpringApplicationContext.getContext().getBean(AsyncServiceExampleService.class);

我需要访问AsyncCallMethodInput参数或更好的参数,将@ServiceContextAwarePoolExecutorContextAwareCallable内的TaskDecorator批注的值添加到配置程序中。

这可以通过将它们添加到上下文中并复制到线程中来完成,但是我需要在Executor或Callable内部添加此逻辑,因为这些是通用方法,并且可以提供不同的异步方法。因此,我不想强​​迫方法编写者向上下文中添加不应手动更改的额外数据。

有没有办法做到这一点?

1 个答案:

答案 0 :(得分:0)

我找到了可行的解决方案。也许会有更好的解决方案,但这就是我唯一能找到的解决方案。

Spring用另一个类包装$ heroku config:set RAILS_MASTER_KEY=<your-master-key-here>,该类具有名为Callable<T> task的属性。当我调试时,此方法包含我的userDeclaredMethod和我需要的所有元数据。所以我需要做的就是访问这些数据。

经过更多研究,我发现了以下方法,即方法。

asyncMethodCall

当我按以下方式调用此方法时,我能够得到所需的东西。

private static Object getField(Object c, String name) throws IllegalAccessException {
        while (c != null && !c.getClass().getName().toLowerCase().equals("java.lang.object")) {
            try {
                Field field = c.getClass().getDeclaredField(name);
                field.setAccessible(true);
                return field.get(c);
            } catch (NoSuchFieldException e) {
                c = c.getClass().getSuperclass();
            }
        }
        return null;
    }

请注意,所有这些代码都在Method asyncMethod = (Method) getField(task, "val$userDeclaredMethod"); 类中。