diff --git a/build-spring-framework/build.xml b/build-spring-framework/build.xml
index 29001858c12..09bf924498a 100644
--- a/build-spring-framework/build.xml
+++ b/build-spring-framework/build.xml
@@ -9,6 +9,7 @@
Subaspects may also need a metadata resolution strategy, in the
+ * BeanWiringInfoResolver interface. The default implementation
+ * looks for a bean with the same name as the FQN. This is the default name
+ * of a bean in a Spring container if the id value is not supplied explicitly.
+ *
+ * @author Rob Harrop
+ * @author Rod Johnson
+ * @author Adrian Colyer
+ * @author Ramnivas Laddad
+ * @since 2.0
+ * @deprecated as of Spring 2.5.2.
+ * Use AbstractDependencyInjectionAspect or its subaspects instead.
+ */
+public abstract aspect AbstractBeanConfigurerAspect extends BeanConfigurerSupport {
+
+ /**
+ * Configured bean before initialization.
+ */
+ @SuppressAjWarnings("adviceDidNotMatch")
+ before(Object beanInstance) : beanInitialization(beanInstance) {
+ if (preConstructionConfiguration(beanInstance)) {
+ configureBean(beanInstance);
+ }
+ }
+
+ /**
+ * Configured bean after construction.
+ */
+ @SuppressAjWarnings("adviceDidNotMatch")
+ after(Object beanInstance) returning : beanCreation(beanInstance) {
+ if (!preConstructionConfiguration(beanInstance)) {
+ configureBean(beanInstance);
+ }
+ }
+
+
+ /**
+ * The initialization of a new object.
+ *
+ *
WARNING: Although this pointcut is non-abstract for backwards + * compatibility reasons, it is meant to be overridden to select + * initialization of any configurable bean. + */ + protected pointcut beanInitialization(Object beanInstance); + + /** + * The creation of a new object. + */ + protected abstract pointcut beanCreation(Object beanInstance); + + + /** + * Are dependencies to be injected prior to the construction of an object? + */ + protected boolean preConstructionConfiguration(Object beanInstance) { + return false; // matches the default in the @Configurable annotation + } + +} diff --git a/org.springframework.aspects/src/main/java/org/springframework/beans/factory/aspectj/AbstractDependencyInjectionAspect.aj b/org.springframework.aspects/src/main/java/org/springframework/beans/factory/aspectj/AbstractDependencyInjectionAspect.aj new file mode 100644 index 00000000000..9008182f024 --- /dev/null +++ b/org.springframework.aspects/src/main/java/org/springframework/beans/factory/aspectj/AbstractDependencyInjectionAspect.aj @@ -0,0 +1,101 @@ +/* + * 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.beans.factory.aspectj; + +import org.aspectj.lang.annotation.SuppressAjWarnings; + +/** + * Abstract base aspect that can perform Dependency + * Injection on objects, however they may be created. + * + * @author Ramnivas Laddad + * @since 2.5.2 + */ +public abstract aspect AbstractDependencyInjectionAspect { + /** + * Select construction join points for objects to inject dependencies + */ + public abstract pointcut beanConstruction(Object bean); + + /** + * Select deserialization join points for objects to inject dependencies + */ + public abstract pointcut beanDeserialization(Object bean); + + /** + * Select join points in a configurable bean + */ + public abstract pointcut inConfigurableBean(); + + /** + * Select join points in beans to be configured prior to construction? + * By default, use post-construction injection matching the default in the Configurable annotation. + */ + public pointcut preConstructionConfiguration() : if(false); + + /** + * Select the most-specific initialization join point + * (most concrete class) for the initialization of an instance. + */ + public pointcut mostSpecificSubTypeConstruction() : + if(thisJoinPoint.getSignature().getDeclaringType() == thisJoinPoint.getThis().getClass()); + + /** + * Select least specific super type that is marked for DI (so that injection occurs only once with pre-construction inejection + */ + public abstract pointcut leastSpecificSuperTypeConstruction(); + + /** + * Configure the bean + */ + public abstract void configureBean(Object bean); + + + private pointcut preConstructionCondition() : + leastSpecificSuperTypeConstruction() && preConstructionConfiguration(); + + private pointcut postConstructionCondition() : + mostSpecificSubTypeConstruction() && !preConstructionConfiguration(); + + /** + * Pre-construction configuration. + */ + @SuppressAjWarnings("adviceDidNotMatch") + before(Object bean) : + beanConstruction(bean) && preConstructionCondition() && inConfigurableBean() { + configureBean(bean); + } + + /** + * Post-construction configuration. + */ + @SuppressAjWarnings("adviceDidNotMatch") + after(Object bean) returning : + beanConstruction(bean) && postConstructionCondition() && inConfigurableBean() { + configureBean(bean); + } + + /** + * Post-deserialization configuration. + */ + @SuppressAjWarnings("adviceDidNotMatch") + after(Object bean) returning : + beanDeserialization(bean) && inConfigurableBean() { + configureBean(bean); + } + +} diff --git a/org.springframework.aspects/src/main/java/org/springframework/beans/factory/aspectj/AbstractInterfaceDrivenDependencyInjectionAspect.aj b/org.springframework.aspects/src/main/java/org/springframework/beans/factory/aspectj/AbstractInterfaceDrivenDependencyInjectionAspect.aj new file mode 100644 index 00000000000..4ecd2923de9 --- /dev/null +++ b/org.springframework.aspects/src/main/java/org/springframework/beans/factory/aspectj/AbstractInterfaceDrivenDependencyInjectionAspect.aj @@ -0,0 +1,124 @@ +/* + * 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.beans.factory.aspectj; + +import java.io.ObjectStreamException; +import java.io.Serializable; + +/** + * An aspect that injects dependency into any object whose type implements the {@link ConfigurableObject} interface. + *
+ * This aspect supports injecting into domain objects when they are created for the first time as well as + * upon deserialization. Subaspects need to simply provide definition for the configureBean() method. This + * method may be implemented without relying on Spring container if so desired. + *
+ *+ * There are two cases that needs to be handled: + *
new' operator: this is
+ * taken care of by advising initialization() join points.private. Since aspects cannot introduce a private member,
+ * while preserving its name, this option is ruled out.public. However, this shouldn't be a big burden, since
+ * use cases that need classes to implement readResolve() (custom enums,
+ * for example) are unlikely to be marked as @Configurable, and
+ * in any case asking to make that method public should not
+ * pose any undue burden.readResolve(), if any, must be
+ * public) can be lifted as well if we were to use an
+ * experimental feature in AspectJ - the hasmethod() PCD.+ * While having type implement the {@link ConfigurableObject} interface is certainly a valid choice, an alternative + * is to use a 'declare parents' statement another aspect (a subaspect of this aspect would be a logical choice) + * that declares the classes that need to be configured by supplying the {@link ConfigurableObject} interface. + *
+ * + * @author Ramnivas Laddad + * @since 2.5.2 + */ +public abstract aspect AbstractInterfaceDrivenDependencyInjectionAspect extends AbstractDependencyInjectionAspect { + /** + * Select initialization join point as object construction + */ + public pointcut beanConstruction(Object bean) : + initialization(ConfigurableObject+.new(..)) && this(bean); + + /** + * Select deserialization join point made available through ITDs for ConfigurableDeserializationSupport + */ + public pointcut beanDeserialization(Object bean) : + execution(Object ConfigurableDeserializationSupport+.readResolve()) && + this(bean); + + public pointcut leastSpecificSuperTypeConstruction() : initialization(ConfigurableObject.new(..)); + + + + // Implementation to support re-injecting dependencies once an object is deserialized + /** + * Declare any class implementing Serializable and ConfigurableObject as also implementing + * ConfigurableDeserializationSupport. This allows us to introduce the readResolve() + * method and select it with the beanDeserialization() pointcut. + * + *Here is an improved version that uses the hasmethod() pointcut and lifts + * even the minor requirement on user classes: + * + *
declare parents: ConfigurableObject+ Serializable+ + * && !hasmethod(Object readResolve() throws ObjectStreamException) + * implements ConfigurableDeserializationSupport; + *+ */ + declare parents: + ConfigurableObject+ && Serializable+ implements ConfigurableDeserializationSupport; + + /** + * A marker interface to which the
readResolve() is introduced.
+ */
+ static interface ConfigurableDeserializationSupport extends Serializable {
+ }
+
+ /**
+ * Introduce the readResolve() method so that we can advise its
+ * execution to configure the object.
+ *
+ * Note if a method with the same signature already exists in a
+ * Serializable class of ConfigurableObject type,
+ * that implementation will take precedence (a good thing, since we are
+ * merely interested in an opportunity to detect deserialization.)
+ */
+ public Object ConfigurableDeserializationSupport.readResolve() throws ObjectStreamException {
+ return this;
+ }
+
+}
diff --git a/org.springframework.aspects/src/main/java/org/springframework/beans/factory/aspectj/AnnotationBeanConfigurerAspect.aj b/org.springframework.aspects/src/main/java/org/springframework/beans/factory/aspectj/AnnotationBeanConfigurerAspect.aj
new file mode 100644
index 00000000000..f9602877200
--- /dev/null
+++ b/org.springframework.aspects/src/main/java/org/springframework/beans/factory/aspectj/AnnotationBeanConfigurerAspect.aj
@@ -0,0 +1,89 @@
+/*
+ * 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.beans.factory.aspectj;
+
+import java.io.Serializable;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.AnnotationBeanWiringInfoResolver;
+import org.springframework.beans.factory.annotation.Configurable;
+import org.springframework.beans.factory.wiring.BeanConfigurerSupport;
+
+/**
+ * Concrete aspect that uses the {@link Configurable}
+ * annotation to identify which classes need autowiring.
+ *
+ *
The bean name to look up will be taken from the
+ * @Configurable annotation if specified, otherwise the
+ * default bean name to look up will be the FQN of the class being configured.
+ *
+ * @author Rod Johnson
+ * @author Ramnivas Laddad
+ * @author Juergen Hoeller
+ * @author Adrian Colyer
+ * @since 2.0
+ * @see org.springframework.beans.factory.annotation.Configurable
+ * @see org.springframework.beans.factory.annotation.AnnotationBeanWiringInfoResolver
+ */
+public aspect AnnotationBeanConfigurerAspect
+ extends AbstractInterfaceDrivenDependencyInjectionAspect
+ implements BeanFactoryAware, InitializingBean, DisposableBean {
+
+ private BeanConfigurerSupport beanConfigurerSupport = new BeanConfigurerSupport();
+
+ public pointcut inConfigurableBean() : @this(Configurable);
+
+ public pointcut preConstructionConfiguration() : preConstructionConfigurationSupport(*);
+
+ declare parents: @Configurable * implements ConfigurableObject;
+
+ public void configureBean(Object bean) {
+ beanConfigurerSupport.configureBean(bean);
+ }
+
+
+ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
+ beanConfigurerSupport.setBeanFactory(beanFactory);
+ beanConfigurerSupport.setBeanWiringInfoResolver(new AnnotationBeanWiringInfoResolver());
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ beanConfigurerSupport.afterPropertiesSet();
+ }
+
+ public void destroy() throws Exception {
+ beanConfigurerSupport.destroy();
+ }
+
+
+ /*
+ * An intermediary to match preConstructionConfiguration signature (that doesn't expose the annotation object)
+ */
+ private pointcut preConstructionConfigurationSupport(Configurable c) : @this(c) && if(c.preConstruction());
+
+ /*
+ * This declaration shouldn't be needed,
+ * except for an AspectJ bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=214559)
+ */
+ declare parents: @Configurable Serializable+
+ implements ConfigurableDeserializationSupport;
+
+}
diff --git a/org.springframework.aspects/src/main/java/org/springframework/beans/factory/aspectj/ConfigurableObject.java b/org.springframework.aspects/src/main/java/org/springframework/beans/factory/aspectj/ConfigurableObject.java
new file mode 100644
index 00000000000..13597f9a97e
--- /dev/null
+++ b/org.springframework.aspects/src/main/java/org/springframework/beans/factory/aspectj/ConfigurableObject.java
@@ -0,0 +1,26 @@
+/*
+ * 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.beans.factory.aspectj;
+
+/**
+ * Marker interface for domain object that need DI through aspects.
+ *
+ * @author Ramnivas Laddad
+ * @since 2.5
+ */
+public interface ConfigurableObject {
+
+}
diff --git a/org.springframework.aspects/src/main/java/org/springframework/transaction/aspectj/AbstractTransactionAspect.aj b/org.springframework.aspects/src/main/java/org/springframework/transaction/aspectj/AbstractTransactionAspect.aj
new file mode 100644
index 00000000000..655b492f769
--- /dev/null
+++ b/org.springframework.aspects/src/main/java/org/springframework/transaction/aspectj/AbstractTransactionAspect.aj
@@ -0,0 +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 transactionalMethodExecution()
+ * pointcut using a strategy such as Java 5 annotations.
+ *
+ *
Suitable for use inside or outside the Spring IoC container. + * Set the "transactionManager" property appropriately, allowing + * use of any transaction implementation supported by Spring. + * + *
NB: If a method implements an interface that is itself + * transactionally annotated, the relevant Spring transaction attribute + * will not 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); + +} diff --git a/org.springframework.aspects/src/main/java/org/springframework/transaction/aspectj/AnnotationTransactionAspect.aj b/org.springframework.aspects/src/main/java/org/springframework/transaction/aspectj/AnnotationTransactionAspect.aj new file mode 100644 index 00000000000..1282b660b73 --- /dev/null +++ b/org.springframework.aspects/src/main/java/org/springframework/transaction/aspectj/AnnotationTransactionAspect.aj @@ -0,0 +1,76 @@ +/* + * 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+. + * + *
When using this aspect, you must annotate the implementation class + * (and/or methods within that class), not the interface (if any) that + * the class implements. AspectJ follows Java's rule that annotations on + * interfaces are not inherited. + * + *
A @Transactional annotation on a class specifies the default transaction + * semantics for the execution of any public operation in the class. + * + *
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); + +} diff --git a/org.springframework.aspects/src/main/java/overview.html b/org.springframework.aspects/src/main/java/overview.html new file mode 100644 index 00000000000..1eb7a2e8c19 --- /dev/null +++ b/org.springframework.aspects/src/main/java/overview.html @@ -0,0 +1,7 @@ + +
++The Spring Data Binding framework, an internal library used by Spring Web Flow. +
+ + \ No newline at end of file diff --git a/org.springframework.aspects/src/main/resources/META-INF/aop.xml b/org.springframework.aspects/src/main/resources/META-INF/aop.xml new file mode 100644 index 00000000000..78a97e6525f --- /dev/null +++ b/org.springframework.aspects/src/main/resources/META-INF/aop.xml @@ -0,0 +1,17 @@ + + + +