org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor.java

Source

/*
 * Copyright 2002-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.scheduling.annotation;

import java.lang.annotation.Annotation;
import java.util.concurrent.Executor;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.aop.framework.autoproxy.AbstractBeanFactoryAwareAdvisingPostProcessor;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.task.TaskExecutor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

/**
 * Bean post-processor that automatically applies asynchronous invocation
 * behavior to any bean that carries the {@link Async} annotation at class or
 * method-level by adding a corresponding {@link AsyncAnnotationAdvisor} to the
 * exposed proxy (either an existing AOP proxy or a newly generated proxy that
 * implements all of the target's interfaces).
 *
 * <p>The {@link TaskExecutor} responsible for the asynchronous execution may
 * be provided as well as the annotation type that indicates a method should be
 * invoked asynchronously. If no annotation type is specified, this post-
 * processor will detect both Spring's {@link Async @Async} annotation as well
 * as the EJB 3.1 {@code javax.ejb.Asynchronous} annotation.
 *
 * <p>For methods having a {@code void} return type, any exception thrown
 * during the asynchronous method invocation cannot be accessed by the
 * caller. An {@link AsyncUncaughtExceptionHandler} can be specified to handle
 * these cases.
 *
 * <p>Note: The underlying async advisor applies before existing advisors by default,
 * in order to switch to async execution as early as possible in the invocation chain.
 *
 * @author Mark Fisher
 * @author Juergen Hoeller
 * @author Stephane Nicoll
 * @since 3.0
 * @see Async
 * @see AsyncAnnotationAdvisor
 * @see #setBeforeExistingAdvisors
 * @see ScheduledAnnotationBeanPostProcessor
 */
@SuppressWarnings("serial")
public class AsyncAnnotationBeanPostProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessor {

    /**
     * The default name of the {@link TaskExecutor} bean to pick up: "taskExecutor".
     * <p>Note that the initial lookup happens by type; this is just the fallback
     * in case of multiple executor beans found in the context.
     * @since 4.2
     * @see AnnotationAsyncExecutionInterceptor#DEFAULT_TASK_EXECUTOR_BEAN_NAME
     */
    public static final String DEFAULT_TASK_EXECUTOR_BEAN_NAME = AnnotationAsyncExecutionInterceptor.DEFAULT_TASK_EXECUTOR_BEAN_NAME;

    protected final Log logger = LogFactory.getLog(getClass());

    @Nullable
    private Class<? extends Annotation> asyncAnnotationType;

    @Nullable
    private Executor executor;

    @Nullable
    private AsyncUncaughtExceptionHandler exceptionHandler;

    public AsyncAnnotationBeanPostProcessor() {
        setBeforeExistingAdvisors(true);
    }

    /**
     * Set the 'async' annotation type to be detected at either class or method
     * level. By default, both the {@link Async} annotation and the EJB 3.1
     * {@code javax.ejb.Asynchronous} annotation will be detected.
     * <p>This setter property exists so that developers can provide their own
     * (non-Spring-specific) annotation type to indicate that a method (or all
     * methods of a given class) should be invoked asynchronously.
     * @param asyncAnnotationType the desired annotation type
     */
    public void setAsyncAnnotationType(Class<? extends Annotation> asyncAnnotationType) {
        Assert.notNull(asyncAnnotationType, "'asyncAnnotationType' must not be null");
        this.asyncAnnotationType = asyncAnnotationType;
    }

    /**
     * Set the {@link Executor} to use when invoking methods asynchronously.
     * <p>If not specified, default executor resolution will apply: searching for a
     * unique {@link TaskExecutor} bean in the context, or for an {@link Executor}
     * bean named "taskExecutor" otherwise. If neither of the two is resolvable,
     * a local default executor will be created within the interceptor.
     * @see AsyncAnnotationAdvisor#AsyncAnnotationAdvisor(Executor, AsyncUncaughtExceptionHandler)
     * @see AnnotationAsyncExecutionInterceptor#getDefaultExecutor(BeanFactory)
     * @see #DEFAULT_TASK_EXECUTOR_BEAN_NAME
     */
    public void setExecutor(Executor executor) {
        this.executor = executor;
    }

    /**
     * Set the {@link AsyncUncaughtExceptionHandler} to use to handle uncaught
     * exceptions thrown by asynchronous method executions.
     * @since 4.1
     */
    public void setExceptionHandler(AsyncUncaughtExceptionHandler exceptionHandler) {
        this.exceptionHandler = exceptionHandler;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        super.setBeanFactory(beanFactory);

        AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler);
        if (this.asyncAnnotationType != null) {
            advisor.setAsyncAnnotationType(this.asyncAnnotationType);
        }
        advisor.setBeanFactory(beanFactory);
        this.advisor = advisor;
    }

}