added @Async annotation, AsyncExecutionInterceptor, AsyncAnnotationAdvisor
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation that marks a method as a candidate for <i>asynchronous</i> execution.
|
||||
* Can also be used at the type level, in which case all of the type's methods are
|
||||
* considered as asynchronous.
|
||||
*
|
||||
* <p>In terms of target method signatures, any parameter types are supported.
|
||||
* However, the return type is constrained to either <code>void</code> or
|
||||
* <code>java.util.concurrent.Future</code>. In the latter case, the Future handle
|
||||
* returned from the proxy will be an actual asynchronous Future that can be used
|
||||
* to track the result of the asynchronous method execution. However, since the
|
||||
* target method needs to implement the same signature, it will have to return
|
||||
* a temporary Future handle that just passes the return value through: e.g.
|
||||
* Spring's {@link AsyncResult} or EJB 3.1's <code>javax.ejb.AsyncResult</code>.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see org.springframework.aop.interceptor.AsyncExecutionInterceptor
|
||||
* @see AsyncAnnotationAdvisor
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Async {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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 java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.interceptor.AsyncExecutionInterceptor;
|
||||
import org.springframework.aop.support.AbstractPointcutAdvisor;
|
||||
import org.springframework.aop.support.ComposablePointcut;
|
||||
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Advisor that activates asynchronous method execution through the {@link Async}
|
||||
* annotation. This annotation can be used at the method and type level in
|
||||
* implementation classes as well as in service interfaces.
|
||||
*
|
||||
* <p>This advisor detects the EJB 3.1 <code>javax.ejb.Asynchronous</code>
|
||||
* annotation as well, treating it exactly like Spring's own <code>Async</code>.
|
||||
* Furthermore, a custom async annotation type may get specified through the
|
||||
* {@link #setAsyncAnnotationType "asyncAnnotationType"} property.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see PersistenceExceptionTranslationAdvisor
|
||||
* @see org.springframework.stereotype.Repository
|
||||
* @see org.springframework.dao.DataAccessException
|
||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator
|
||||
*/
|
||||
public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor {
|
||||
|
||||
private Advice advice;
|
||||
|
||||
private Pointcut pointcut;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new ConcurrencyAnnotationBeanPostProcessor for bean-style configuration.
|
||||
*/
|
||||
public AsyncAnnotationAdvisor() {
|
||||
this(new SimpleAsyncTaskExecutor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ConcurrencyAnnotationBeanPostProcessor for the given task executor.
|
||||
* @param executor the task executor to use for asynchronous methods
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public AsyncAnnotationAdvisor(Executor executor) {
|
||||
Set<Class<? extends Annotation>> asyncAnnotationTypes = new LinkedHashSet<Class<? extends Annotation>>(2);
|
||||
asyncAnnotationTypes.add(Async.class);
|
||||
try {
|
||||
asyncAnnotationTypes.add(ClassUtils.forName(
|
||||
"javax.ejb.Asynchronous", AsyncAnnotationAdvisor.class.getClassLoader()));
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// If EJB 3.1 API not present, simply ignore.
|
||||
}
|
||||
this.advice = buildAdvice(executor);
|
||||
this.pointcut = buildPointcut(asyncAnnotationTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the task executor to use for asynchronous methods.
|
||||
*/
|
||||
public void setTaskExecutor(Executor executor) {
|
||||
this.advice = buildAdvice(executor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'async' annotation type.
|
||||
* <p>The default async annotation type is the {@link Async} annotation, as well
|
||||
* as the EJB 3.1 <code>javax.ejb.Asynchronous</code> annotation (if present).
|
||||
* <p>This setter property exists so that developers can provide their own
|
||||
* (non-Spring-specific) annotation type to indicate that a method is to
|
||||
* be executed asynchronously.
|
||||
* @param asyncAnnotationType the desired annotation type
|
||||
*/
|
||||
public void setAsyncAnnotationType(Class<? extends Annotation> asyncAnnotationType) {
|
||||
Assert.notNull(asyncAnnotationType, "'asyncAnnotationType' must not be null");
|
||||
Set<Class<? extends Annotation>> asyncAnnotationTypes = new HashSet<Class<? extends Annotation>>();
|
||||
asyncAnnotationTypes.add(asyncAnnotationType);
|
||||
this.pointcut = buildPointcut(asyncAnnotationTypes);
|
||||
}
|
||||
|
||||
|
||||
public Advice getAdvice() {
|
||||
return this.advice;
|
||||
}
|
||||
|
||||
public Pointcut getPointcut() {
|
||||
return this.pointcut;
|
||||
}
|
||||
|
||||
|
||||
protected Advice buildAdvice(Executor executor) {
|
||||
if (executor instanceof AsyncTaskExecutor) {
|
||||
return new AsyncExecutionInterceptor((AsyncTaskExecutor) executor);
|
||||
}
|
||||
else {
|
||||
return new AsyncExecutionInterceptor(executor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate a pointcut for the given target class, if any.
|
||||
* @param targetClass the class to introspect
|
||||
* @return the applicable Pointcut object, or <code>null</code> if none
|
||||
*/
|
||||
protected Pointcut buildPointcut(Set<Class<? extends Annotation>> asyncAnnotationTypes) {
|
||||
ComposablePointcut result = null;
|
||||
for (Class<? extends Annotation> asyncAnnotationType : asyncAnnotationTypes) {
|
||||
Pointcut cpc = new AnnotationMatchingPointcut(asyncAnnotationType, true);
|
||||
Pointcut mpc = new AnnotationMatchingPointcut(null, asyncAnnotationType);
|
||||
if (result == null) {
|
||||
result = new ComposablePointcut(cpc).union(mpc);
|
||||
}
|
||||
else {
|
||||
result.union(cpc).union(mpc);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* A pass-through <code>Future</code> handle that can be used for method signatures
|
||||
* which are declared with a Future return type for asynchronous execution.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see org.springframework.scheduling.annotation.Async
|
||||
*/
|
||||
public class AsyncResult<V> implements Future<V> {
|
||||
|
||||
private final V value;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new AsyncResult holder.
|
||||
* @param value the value to pass through
|
||||
*/
|
||||
public AsyncResult(V value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public V get() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public V get(long timeout, TimeUnit unit) {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<body>
|
||||
|
||||
JDK 1.5+ annotation for asynchronous method execution.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user