initial commit of the AsyncAnnotationBeanPostProcessor
This commit is contained in:
parent
e67aa6cbb2
commit
3b42200cda
|
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 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 org.springframework.aop.framework.Advised;
|
||||||
|
import org.springframework.aop.framework.AopInfrastructureBean;
|
||||||
|
import org.springframework.aop.framework.ProxyConfig;
|
||||||
|
import org.springframework.aop.framework.ProxyFactory;
|
||||||
|
import org.springframework.aop.support.AopUtils;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||||
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
|
import org.springframework.beans.factory.BeanFactoryAware;
|
||||||
|
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.core.task.TaskExecutor;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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</code> annotation.
|
||||||
|
*
|
||||||
|
* @author Mark Fisher
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
|
* @see Async
|
||||||
|
* @see AsyncAnnotationAdvisor
|
||||||
|
*/
|
||||||
|
public class AsyncAnnotationBeanPostProcessor extends ProxyConfig
|
||||||
|
implements BeanPostProcessor, BeanClassLoaderAware, BeanFactoryAware, Ordered {
|
||||||
|
|
||||||
|
private Class<? extends Annotation> asyncAnnotationType;
|
||||||
|
|
||||||
|
private Executor executor;
|
||||||
|
|
||||||
|
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
|
||||||
|
|
||||||
|
private AsyncAnnotationAdvisor asyncAnnotationAdvisor;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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</code> 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.
|
||||||
|
*/
|
||||||
|
public void setExecutor(Executor executor) {
|
||||||
|
this.executor = executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||||
|
this.beanClassLoader = classLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||||
|
this.asyncAnnotationAdvisor = (this.executor != null) ?
|
||||||
|
new AsyncAnnotationAdvisor(this.executor) : new AsyncAnnotationAdvisor();
|
||||||
|
if (this.asyncAnnotationType != null) {
|
||||||
|
this.asyncAnnotationAdvisor.setAsyncAnnotationType(asyncAnnotationType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOrder() {
|
||||||
|
// This should run after all other post-processors, so that it can just add
|
||||||
|
// an advisor to existing proxies rather than double-proxy.
|
||||||
|
return LOWEST_PRECEDENCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||||
|
if (bean instanceof AopInfrastructureBean) {
|
||||||
|
// Ignore AOP infrastructure such as scoped proxies.
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<?> targetClass = AopUtils.getTargetClass(bean);
|
||||||
|
if (targetClass == null) {
|
||||||
|
// Can't do much here.
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AopUtils.canApply(this.asyncAnnotationAdvisor, targetClass)) {
|
||||||
|
if (bean instanceof Advised) {
|
||||||
|
((Advised) bean).addAdvisor(this.asyncAnnotationAdvisor);
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ProxyFactory proxyFactory = new ProxyFactory(bean);
|
||||||
|
// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
|
||||||
|
proxyFactory.copyFrom(this);
|
||||||
|
proxyFactory.addAdvisor(this.asyncAnnotationAdvisor);
|
||||||
|
return proxyFactory.getProxy(this.beanClassLoader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// No async proxy needed.
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue