java.lang.reflect.Method.invoke和Spring @Async

时间:2015-04-09 11:08:23

标签: multithreading spring asynchronous reflection java.util.concurrent

我有一个场景,如果某个方法有特定的注释,则需要调用该方法。该方法还需要在一个单独的线程中运行,因此我使用了@Async,但它并不是同时运行的。

如果未使用java.lang.reflect.Method.invoke并且使用了旧的Object.methodName(),则该方法会异步运行。

这种情况有限制吗?我正在使用JDK 1.7和Spring 4.x。

我在applicationContext.xml中有以下内容: <task:annotation-driven />

该类(基本上是一个监听器/回调):

@Service
@BackgroundJob
public class ItemHold {
private XLogger logger = XLoggerFactory.getXLogger(ItemHoldAnnotation.class
        .getName());

@Async
private void doItemHoldCheck() {
    try {
        Thread.sleep(30 * 1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

}

@BackgroundJobCallback
public void mangoesTasteGood() {
    logger.error("...tick...");
    doItemHoldCheck();
}
}

来电者:

@Service
public class BatchServiceAnnotationImpl implements BatchService {

private XLogger logger = XLoggerFactory
        .getXLogger(BatchServiceAnnotationImpl.class.getName());

@Inject
ApplicationContext context;

Map<Object, Method> mJobMap = new HashMap<Object, Method>();

@Scheduled(cron = "0/5 * * * * ?")
public void timer() {
    performBatchJobs();

}

private void performBatchJobs() {
    for (Map.Entry<Object, Method> entry : mJobMap.entrySet()) {
        try {
            Object object = entry.getKey();
            Method method = entry.getValue();

            method.invoke(object, null);
        } catch (IllegalAccessException e) {
            throw new AppServiceException(
                    "Failed to perform Background Job", e);
        } catch (IllegalArgumentException e) {
            throw new AppServiceException(
                    "Failed to perform Background Job", e);
        } catch (InvocationTargetException e) {
            throw new AppServiceException(
                    "Failed to perform Background Job", e);
        }
    }
}

@PostConstruct
public void init() {
    /*
     * Annotation based: Detect any Bean having BackgroundJob annotation.
     * Then find the method annotated with BackgroundJobCallback.
     */
    Map<String, Object> beans = context
            .getBeansWithAnnotation(BackgroundJob.class);
    for (Map.Entry<String, Object> entry : beans.entrySet()) {
        Object backgroundJob = entry.getValue();
        Class<?> clazz = backgroundJob.getClass();
        for (Method method : clazz.getDeclaredMethods()) {
            if (method.isAnnotationPresent(BackgroundJobCallback.class)) {
                mJobMap.put(backgroundJob, method);
            }
        }
    }
}
}

0 个答案:

没有答案