All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor Maven / Gradle / Ivy

There is a newer version: 6.1.6
Show newest version
/*
 * Copyright 2002-2022 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
 *
 *      https://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 java.util.function.Supplier;

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;
import org.springframework.util.function.SingletonSupplier;

/**
 * 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 the target's interfaces).
 *
 * 

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 jakarta.ejb.Asynchronous} annotation. * *

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. * *

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". *

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 Supplier executor; @Nullable private Supplier exceptionHandler; @Nullable private Class asyncAnnotationType; public AsyncAnnotationBeanPostProcessor() { setBeforeExistingAdvisors(true); } /** * Configure this post-processor with the given executor and exception handler suppliers, * applying the corresponding default if a supplier is not resolvable. * @since 5.1 */ public void configure( @Nullable Supplier executor, @Nullable Supplier exceptionHandler) { this.executor = executor; this.exceptionHandler = exceptionHandler; } /** * Set the {@link Executor} to use when invoking methods asynchronously. *

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 AnnotationAsyncExecutionInterceptor#getDefaultExecutor(BeanFactory) * @see #DEFAULT_TASK_EXECUTOR_BEAN_NAME */ public void setExecutor(Executor executor) { this.executor = SingletonSupplier.of(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 = SingletonSupplier.of(exceptionHandler); } /** * 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 jakarta.ejb.Asynchronous} annotation will be detected. *

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 asyncAnnotationType) { Assert.notNull(asyncAnnotationType, "'asyncAnnotationType' must not be null"); this.asyncAnnotationType = asyncAnnotationType; } @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; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy