|
Spring Framework example source code file (AbstractInterfaceDrivenDependencyInjectionAspect.aj)
This example Spring Framework source code file (AbstractInterfaceDrivenDependencyInjectionAspect.aj) is included in the DevDaily.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.
The Spring Framework AbstractInterfaceDrivenDependencyInjectionAspect.aj source code
/*
* 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.
* <p>
* 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.
* </p>
* <p>
* There are two cases that needs to be handled:
* <ol>
* <li>Normal object creation via the 'new ' operator: this is
* taken care of by advising <code>initialization() join points.
* <li>Object creation through deserialization: since no constructor is
* invoked during deserialization, the aspect needs to advise a method that a
* deserialization mechanism is going to invoke. Ideally, we should not
* require user classes to implement any specific method. This implies that
* we need to <i>introduce the chosen method. We should also handle the cases
* where the chosen method is already implemented in classes (in which case,
* the user's implementation for that method should take precedence over the
* introduced implementation). There are a few choices for the chosen method:
* <ul>
* <li>readObject(ObjectOutputStream): Java requires that the method must be
* <code>private. Since aspects cannot introduce a private member,
* while preserving its name, this option is ruled out.</li>
* <li>readResolve(): Java doesn't pose any restriction on an access specifier.
* Problem solved! There is one (minor) limitation of this approach in
* that if a user class already has this method, that method must be
* <code>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 <code>public should not
* pose any undue burden.</li>
* </ul>
* The minor collaboration needed by user classes (i.e., that the
* implementation of <code>readResolve(), if any, must be
* <code>public) can be lifted as well if we were to use an
* experimental feature in AspectJ - the <code>hasmethod() PCD.
* </ol>
* <p>
* 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.
* </p>
*
* @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.
*
* <p>Here is an improved version that uses the hasmethod() pointcut and lifts
* even the minor requirement on user classes:
*
* <pre class="code">declare parents: ConfigurableObject+ Serializable+
* && !hasmethod(Object readResolve() throws ObjectStreamException)
* implements ConfigurableDeserializationSupport;
* </pre>
*/
declare parents:
ConfigurableObject+ && Serializable+ implements ConfigurableDeserializationSupport;
/**
* A marker interface to which the <code>readResolve() is introduced.
*/
static interface ConfigurableDeserializationSupport extends Serializable {
}
/**
* Introduce the <code>readResolve() method so that we can advise its
* execution to configure the object.
*
* <p>Note if a method with the same signature already exists in a
* <code>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;
}
}
Other Spring Framework examples (source code examples)
Here is a short list of links related to this Spring Framework AbstractInterfaceDrivenDependencyInjectionAspect.aj source code file:
|