added mode="proxy"/"aspectj" and proxy-target-class options to task namespace; switched to concise names for async aspects

This commit is contained in:
Juergen Hoeller
2010-10-15 20:50:23 +00:00
parent 171f1ee097
commit 8c9b64c948
10 changed files with 324 additions and 218 deletions

View File

@@ -28,22 +28,18 @@ import org.springframework.core.task.support.TaskExecutorAdapter;
/**
* Abstract aspect that routes selected methods asynchronously.
*
* <p>This aspect, by default, uses {@link SimpleAsyncTaskExecutor} to route
* method execution. However, you may inject it with any implementation of
* {@link Executor} to override the default.
* <p>This aspect needs to be injected with an implementation of
* {@link Executor} to activate it for a specific thread pool.
* Otherwise it will simply delegate all calls synchronously.
*
* @author Ramnivas Laddad
* @author Juergen Hoeller
* @since 3.0.5
*/
public abstract aspect AbstractAsynchronousExecutionAspect {
public abstract aspect AbstractAsyncExecutionAspect {
private AsyncTaskExecutor asyncExecutor;
public AbstractAsynchronousExecutionAspect() {
// Set default executor, which may be replaced by calling setExecutor.
setExecutor(new SimpleAsyncTaskExecutor());
}
public void setExecutor(Executor executor) {
if (executor instanceof AsyncTaskExecutor) {
this.asyncExecutor = (AsyncTaskExecutor) executor;
@@ -54,6 +50,9 @@ public abstract aspect AbstractAsynchronousExecutionAspect {
}
Object around() : asyncMethod() {
if (this.asyncExecutor == null) {
return proceed();
}
Callable<Object> callable = new Callable<Object>() {
public Object call() throws Exception {
Object result = proceed();
@@ -62,7 +61,7 @@ public abstract aspect AbstractAsynchronousExecutionAspect {
}
return null;
}};
Future<?> result = asyncExecutor.submit(callable);
Future<?> result = this.asyncExecutor.submit(callable);
if (Future.class.isAssignableFrom(((MethodSignature) thisJoinPointStaticPart.getSignature()).getReturnType())) {
return result;
}

View File

@@ -33,7 +33,7 @@ import org.springframework.scheduling.annotation.Async;
* @author Ramnivas Laddad
* @since 3.0.5
*/
public aspect AnnotationDrivenAsynchronousExecutionAspect extends AbstractAsynchronousExecutionAspect {
public aspect AnnotationAsyncExecutionAspect extends AbstractAsyncExecutionAspect {
private pointcut asyncMarkedMethod()
: execution(@Async (void || Future+) *(..));

View File

@@ -1,93 +1,93 @@
/*
* Copyright 2002-2007 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.transaction.aspectj;
import java.lang.reflect.Method;
import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
/**
* Abstract superaspect for AspectJ transaction aspects. Concrete
* subaspects will implement the <code>transactionalMethodExecution()</code>
* pointcut using a strategy such as Java 5 annotations.
*
* <p>Suitable for use inside or outside the Spring IoC container.
* Set the "transactionManager" property appropriately, allowing
* use of any transaction implementation supported by Spring.
*
* <p><b>NB:</b> If a method implements an interface that is itself
* transactionally annotated, the relevant Spring transaction attribute
* will <i>not</i> be resolved. This behavior will vary from that of Spring AOP
* if proxying an interface (but not when proxying a class). We recommend that
* transaction annotations should be added to classes, rather than business
* interfaces, as they are an implementation detail rather than a contract
* specification validation.
*
* @author Rod Johnson
* @author Ramnivas Laddad
* @since 2.0
*/
public abstract aspect AbstractTransactionAspect extends TransactionAspectSupport {
/**
* Construct object using the given transaction metadata retrieval strategy.
* @param tas TransactionAttributeSource implementation, retrieving Spring
* transaction metadata for each joinpoint. Write the subclass to pass in null
* if it's intended to be configured by Setter Injection.
*/
protected AbstractTransactionAspect(TransactionAttributeSource tas) {
setTransactionAttributeSource(tas);
}
@SuppressAjWarnings("adviceDidNotMatch")
before(Object txObject) : transactionalMethodExecution(txObject) {
MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
Method method = methodSignature.getMethod();
TransactionInfo txInfo = createTransactionIfNecessary(method, txObject.getClass());
}
@SuppressAjWarnings("adviceDidNotMatch")
after(Object txObject) throwing(Throwable t) : transactionalMethodExecution(txObject) {
try {
completeTransactionAfterThrowing(TransactionAspectSupport.currentTransactionInfo(), t);
}
catch (Throwable t2) {
logger.error("Failed to close transaction after throwing in a transactional method", t2);
}
}
@SuppressAjWarnings("adviceDidNotMatch")
after(Object txObject) returning() : transactionalMethodExecution(txObject) {
commitTransactionAfterReturning(TransactionAspectSupport.currentTransactionInfo());
}
@SuppressAjWarnings("adviceDidNotMatch")
after(Object txObject) : transactionalMethodExecution(txObject) {
cleanupTransactionInfo(TransactionAspectSupport.currentTransactionInfo());
}
/**
* Concrete subaspects must implement this pointcut, to identify
* transactional methods. For each selected joinpoint, TransactionMetadata
* will be retrieved using Spring's TransactionAttributeSource interface.
*/
protected abstract pointcut transactionalMethodExecution(Object txObject);
}
/*
* Copyright 2002-2010 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.transaction.aspectj;
import java.lang.reflect.Method;
import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
/**
* Abstract superaspect for AspectJ transaction aspects. Concrete
* subaspects will implement the <code>transactionalMethodExecution()</code>
* pointcut using a strategy such as Java 5 annotations.
*
* <p>Suitable for use inside or outside the Spring IoC container.
* Set the "transactionManager" property appropriately, allowing
* use of any transaction implementation supported by Spring.
*
* <p><b>NB:</b> If a method implements an interface that is itself
* transactionally annotated, the relevant Spring transaction attribute
* will <i>not</i> be resolved. This behavior will vary from that of Spring AOP
* if proxying an interface (but not when proxying a class). We recommend that
* transaction annotations should be added to classes, rather than business
* interfaces, as they are an implementation detail rather than a contract
* specification validation.
*
* @author Rod Johnson
* @author Ramnivas Laddad
* @since 2.0
*/
public abstract aspect AbstractTransactionAspect extends TransactionAspectSupport {
/**
* Construct object using the given transaction metadata retrieval strategy.
* @param tas TransactionAttributeSource implementation, retrieving Spring
* transaction metadata for each joinpoint. Write the subclass to pass in null
* if it's intended to be configured by Setter Injection.
*/
protected AbstractTransactionAspect(TransactionAttributeSource tas) {
setTransactionAttributeSource(tas);
}
@SuppressAjWarnings("adviceDidNotMatch")
before(Object txObject) : transactionalMethodExecution(txObject) {
MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
Method method = methodSignature.getMethod();
TransactionInfo txInfo = createTransactionIfNecessary(method, txObject.getClass());
}
@SuppressAjWarnings("adviceDidNotMatch")
after(Object txObject) throwing(Throwable t) : transactionalMethodExecution(txObject) {
try {
completeTransactionAfterThrowing(TransactionAspectSupport.currentTransactionInfo(), t);
}
catch (Throwable t2) {
logger.error("Failed to close transaction after throwing in a transactional method", t2);
}
}
@SuppressAjWarnings("adviceDidNotMatch")
after(Object txObject) returning() : transactionalMethodExecution(txObject) {
commitTransactionAfterReturning(TransactionAspectSupport.currentTransactionInfo());
}
@SuppressAjWarnings("adviceDidNotMatch")
after(Object txObject) : transactionalMethodExecution(txObject) {
cleanupTransactionInfo(TransactionAspectSupport.currentTransactionInfo());
}
/**
* Concrete subaspects must implement this pointcut, to identify
* transactional methods. For each selected joinpoint, TransactionMetadata
* will be retrieved using Spring's TransactionAttributeSource interface.
*/
protected abstract pointcut transactionalMethodExecution(Object txObject);
}

View File

@@ -1,76 +1,75 @@
/*
* Copyright 2002-2008 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.transaction.aspectj;
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
import org.springframework.transaction.annotation.Transactional;
/**
* Concrete AspectJ transaction aspect using Spring Transactional annotation
* for JDK 1.5+.
*
* <p>When using this aspect, you <i>must</i> annotate the implementation class
* (and/or methods within that class), <i>not</i> the interface (if any) that
* the class implements. AspectJ follows Java's rule that annotations on
* interfaces are <i>not</i> inherited.
*
* <p>A @Transactional annotation on a class specifies the default transaction
* semantics for the execution of any <b>public</b> operation in the class.
*
* <p>A @Transactional annotation on a method within the class overrides the
* default transaction semantics given by the class annotation (if present).
* Any method may be annotated (regardless of visibility).
* Annotating non-public methods directly is the only way
* to get transaction demarcation for the execution of such operations.
*
* @author Rod Johnson
* @author Ramnivas Laddad
* @author Adrian Colyer
* @since 2.0
* @see org.springframework.transaction.annotation.Transactional
*/
public aspect AnnotationTransactionAspect extends AbstractTransactionAspect {
public AnnotationTransactionAspect() {
super(new AnnotationTransactionAttributeSource(false));
}
/**
* Matches the execution of any public method in a type with the
* Transactional annotation, or any subtype of a type with the
* Transactional annotation.
*/
private pointcut executionOfAnyPublicMethodInAtTransactionalType() :
execution(public * ((@Transactional *)+).*(..)) && @this(Transactional);
/**
* Matches the execution of any method with the
* Transactional annotation.
*/
private pointcut executionOfTransactionalMethod() :
execution(* *(..)) && @annotation(Transactional);
/**
* Definition of pointcut from super aspect - matched join points
* will have Spring transaction management applied.
*/
protected pointcut transactionalMethodExecution(Object txObject) :
(executionOfAnyPublicMethodInAtTransactionalType()
|| executionOfTransactionalMethod() )
&& this(txObject);
}
/*
* Copyright 2002-2010 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.transaction.aspectj;
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
import org.springframework.transaction.annotation.Transactional;
/**
* Concrete AspectJ transaction aspect using Spring's @Transactional annotation.
*
* <p>When using this aspect, you <i>must</i> annotate the implementation class
* (and/or methods within that class), <i>not</i> the interface (if any) that
* the class implements. AspectJ follows Java's rule that annotations on
* interfaces are <i>not</i> inherited.
*
* <p>A @Transactional annotation on a class specifies the default transaction
* semantics for the execution of any <b>public</b> operation in the class.
*
* <p>A @Transactional annotation on a method within the class overrides the
* default transaction semantics given by the class annotation (if present).
* Any method may be annotated (regardless of visibility).
* Annotating non-public methods directly is the only way
* to get transaction demarcation for the execution of such operations.
*
* @author Rod Johnson
* @author Ramnivas Laddad
* @author Adrian Colyer
* @since 2.0
* @see org.springframework.transaction.annotation.Transactional
*/
public aspect AnnotationTransactionAspect extends AbstractTransactionAspect {
public AnnotationTransactionAspect() {
super(new AnnotationTransactionAttributeSource(false));
}
/**
* Matches the execution of any public method in a type with the
* Transactional annotation, or any subtype of a type with the
* Transactional annotation.
*/
private pointcut executionOfAnyPublicMethodInAtTransactionalType() :
execution(public * ((@Transactional *)+).*(..)) && @this(Transactional);
/**
* Matches the execution of any method with the
* Transactional annotation.
*/
private pointcut executionOfTransactionalMethod() :
execution(* *(..)) && @annotation(Transactional);
/**
* Definition of pointcut from super aspect - matched join points
* will have Spring transaction management applied.
*/
protected pointcut transactionalMethodExecution(Object txObject) :
(executionOfAnyPublicMethodInAtTransactionalType()
|| executionOfTransactionalMethod() )
&& this(txObject);
}