[Jguiraffe-developers] SF.net SVN: jguiraffe:[207] trunk/core/src
Brought to you by:
oheger
|
From: <oh...@us...> - 2012-02-09 07:30:25
|
Revision: 207
http://jguiraffe.svn.sourceforge.net/jguiraffe/?rev=207&view=rev
Author: oheger
Date: 2012-02-09 07:30:13 +0000 (Thu, 09 Feb 2012)
Log Message:
-----------
[3480996] Improvements of DI framework related to builder classes and factory beans.
Modified Paths:
--------------
trunk/core/src/changes/changes.xml
trunk/core/src/main/java/net/sf/jguiraffe/di/impl/ChainedInvocation.java
trunk/core/src/main/java/net/sf/jguiraffe/di/impl/Invocation.java
trunk/core/src/main/java/net/sf/jguiraffe/di/impl/MethodInvocation.java
trunk/core/src/main/java/net/sf/jguiraffe/di/impl/NullInvocation.java
trunk/core/src/main/java/net/sf/jguiraffe/di/impl/providers/LifeCycleBeanProvider.java
trunk/core/src/main/java/net/sf/jguiraffe/di/impl/providers/SingletonBeanProvider.java
trunk/core/src/main/java/net/sf/jguiraffe/gui/builder/di/tags/BeanTag.java
trunk/core/src/main/java/net/sf/jguiraffe/gui/builder/di/tags/DITagLibrary.java
trunk/core/src/main/java/net/sf/jguiraffe/gui/builder/di/tags/DependencyTag.java
trunk/core/src/main/java/net/sf/jguiraffe/gui/builder/di/tags/MethodInvocationTag.java
trunk/core/src/site/xdoc/userguide/dibuilder.xml
trunk/core/src/site/xdoc/userguide/user_guide.xml
trunk/core/src/test/java/net/sf/jguiraffe/di/ReflectionTestClass.java
trunk/core/src/test/java/net/sf/jguiraffe/di/impl/AbstractInvocationTest.java
trunk/core/src/test/java/net/sf/jguiraffe/di/impl/TestChainedInvocation.java
trunk/core/src/test/java/net/sf/jguiraffe/di/impl/TestMethodInvocation.java
trunk/core/src/test/java/net/sf/jguiraffe/di/impl/TestNullInvocation.java
trunk/core/src/test/java/net/sf/jguiraffe/di/impl/providers/TestBeanProviders.java
trunk/core/src/test/java/net/sf/jguiraffe/di/impl/providers/TestLifeCycleBeanProvider.java
trunk/core/src/test/java/net/sf/jguiraffe/di/impl/providers/TestSingletonBeanProvider.java
trunk/core/src/test/java/net/sf/jguiraffe/gui/builder/di/tags/TestBeanTag.java
trunk/core/src/test/java/net/sf/jguiraffe/gui/builder/di/tags/TestInvocationTags.java
trunk/core/src/test/java/net/sf/jguiraffe/gui/builder/di/tags/TestShutdownHandlerTag.java
trunk/core/src/test/java/net/sf/jguiraffe/gui/builder/impl/TestJellyBeanBuilder.java
trunk/core/src/test/resources/jelly_scripts/di.jelly
Added Paths:
-----------
trunk/core/src/main/java/net/sf/jguiraffe/di/impl/providers/HelperInvocations.java
trunk/core/src/main/java/net/sf/jguiraffe/gui/builder/di/tags/InvocationTargetTag.java
trunk/core/src/test/java/net/sf/jguiraffe/di/impl/providers/TestHelperInvocations.java
trunk/core/src/test/java/net/sf/jguiraffe/gui/builder/di/tags/TestInvocationTargetTag.java
Modified: trunk/core/src/changes/changes.xml
===================================================================
--- trunk/core/src/changes/changes.xml 2012-01-29 18:39:57 UTC (rev 206)
+++ trunk/core/src/changes/changes.xml 2012-02-09 07:30:13 UTC (rev 207)
@@ -27,6 +27,10 @@
</properties>
<body>
<release version="1.1" date="in SVN" description="TBD">
+ <action dev="oheger" issue="3480996" type="add">
+ Improvements of the dependency injection framework related to factory
+ beans and builder classes.
+ </action>
<action dev="oheger" issue="3380233" type="add">
SwingTableComponentHandler now ensures that a newly selected row
(in single-selection mode) becomes visible. If necessary, it changes the
Modified: trunk/core/src/main/java/net/sf/jguiraffe/di/impl/ChainedInvocation.java
===================================================================
--- trunk/core/src/main/java/net/sf/jguiraffe/di/impl/ChainedInvocation.java 2012-01-29 18:39:57 UTC (rev 206)
+++ trunk/core/src/main/java/net/sf/jguiraffe/di/impl/ChainedInvocation.java 2012-02-09 07:30:13 UTC (rev 207)
@@ -16,6 +16,7 @@
package net.sf.jguiraffe.di.impl;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
@@ -31,28 +32,28 @@
/**
* <p>
- * A special implementation of the <code>Invokable</code> interface that
- * allows aggregating an arbitrary number of <code>Invokable</code> objects to
+ * A special implementation of the {@code Invokable} interface that
+ * allows aggregating an arbitrary number of {@code Invokable} objects to
* a kind of script.
* </p>
* <p>
* The idea behind this class is that other objects implementing the
- * <code>Invokable</code> interface can be added. They can then be executed en
+ * {@code Invokable} interface can be added. They can then be executed en
* bloc. In addition to that a rudimentary support for variables is available:
* the result of an invocation can be assigned to a named variable; later this
* variable can be accessed again using a special
* {@link Dependency}, which can be created by calling the
- * <code>getChainDependency()</code> method.
+ * {@code getChainDependency()} method.
* </p>
* <p>
* The typical life-cycle of an instance of this class is as follows:
* <ol>
* <li>An instance is created using the default constructor.</li>
- * <li>The <code>Invokable</code> objects to be executed are added using the
- * <code>addInvokable()</code> methods. Note that the order of these calls is
+ * <li>The {@code Invokable} objects to be executed are added using the
+ * {@code addInvokable()} methods. Note that the order of these calls is
* important; the added objects are invoked in exactly the same order.</li>
- * <li>After adding all <code>Invokable</code> objects the
- * <code>invoke()</code> method can be called. It triggers all contained
+ * <li>After adding all {@code Invokable} objects the
+ * {@code invoke()} method can be called. It triggers all contained
* objects.</li>
* </ol>
* By making use of different invocation implementations, indeed a kind of
@@ -88,14 +89,17 @@
/** A cache for the so far created chain dependencies. */
private final Map<String, ChainDependency> chainDependencies;
- /** Stores a list with the contained <code>Invokable</code> objects. */
+ /** Stores a list with the contained {@code Invokable} objects. */
private final List<ChainInvocationData> invokables;
+ /** The name of the result variable. */
+ private String resultVariableName;
+
/** A flag whether the variables are to be cleared before an invocation. */
private boolean clearVariables;
/**
- * Creates a new instance of <code>ChainedInvocation</code>
+ * Creates a new instance of {@code ChainedInvocation}.
*/
public ChainedInvocation()
{
@@ -106,11 +110,11 @@
}
/**
- * Adds the specified <code>Invokable</code> object to this object. It
+ * Adds the specified {@code Invokable} object to this object. It
* will become part of the invocation sequence.
*
* @param inv the object to be added (must not be <b>null</b>)
- * @throws IllegalArgumentException if the passed in <code>Invokable</code>
+ * @throws IllegalArgumentException if the passed in {@code Invokable}
* object is <b>null</b>
*/
public void addInvokable(Invokable inv)
@@ -119,14 +123,14 @@
}
/**
- * Adds the specified <code>Invokable</code> object to this object and
+ * Adds the specified {@code Invokable} object to this object and
* initializes its result variable. It will become part of the invocation
* sequence. The result of its invocation will be stored in a local variable
* with the given name.
*
* @param inv the object to be added (must not be <b>null</b>)
* @param result the name of the result variable
- * @throws IllegalArgumentException if the passed in <code>Invokable</code>
+ * @throws IllegalArgumentException if the passed in {@code Invokable}
* object is <b>null</b>
*/
public void addInvokable(Invokable inv, String result)
@@ -135,7 +139,7 @@
}
/**
- * Adds the specified <code>Invokable</code> object to this object and
+ * Adds the specified {@code Invokable} object to this object and
* initializes its result variable and its source object. It will become
* part of the invocation sequence. The result of its invocation will be
* stored in a local variable with the given name. The invocation is not
@@ -147,7 +151,7 @@
* @param result the name of the result variable
* @param source the name of the variable, which contains the target object
* for this invocation
- * @throws IllegalArgumentException if the passed in <code>Invokable</code>
+ * @throws IllegalArgumentException if the passed in {@code Invokable}
* object is <b>null</b>
*/
public void addInvokable(Invokable inv, String result, String source)
@@ -160,7 +164,7 @@
}
/**
- * Returns a list with the <code>Invokable</code> objects that have
+ * Returns a list with the {@code Invokable} objects that have
* already been added to this chain. Manipulations of this list do not
* affect this object. It is empty if nothing has been added yet.
*
@@ -177,7 +181,7 @@
}
/**
- * Returns the number of <code>Invokable</code> objects contained in this
+ * Returns the number of {@code Invokable} objects contained in this
* chain.
*
* @return the size of this chain
@@ -188,10 +192,10 @@
}
/**
- * Returns a special <code>Dependency</code> for a local variable that is
- * used during the execution of a <code>ChainedInvocation</code>. Local
+ * Returns a special {@code Dependency} for a local variable that is
+ * used during the execution of a {@code ChainedInvocation}. Local
* variables are created by specifying result names for
- * <code>Invokable</code>s when they are added to the chain: the result
+ * {@code Invokable}s when they are added to the chain: the result
* of this invocation will then be stored in a variable with this name. If
* this variable later needs to be used for another invocation (e.g. as the
* parameter of a method call), it can be accessed using such a dependency.
@@ -199,28 +203,32 @@
* @param name the name of the local variable to be accessed (must not be
* <b>null</b>)
* @return the dependency for accessing the specified local variable
- * @throws IllegalArgumentException if the name is undefined
+ * @throws IllegalArgumentException if the name is <b>null</b>
*/
public Dependency getChainDependency(String name)
{
- if (name == null)
- {
- throw new IllegalArgumentException(
- "Variable name must not be null!");
- }
+ return fetchVariableDependency(name);
+ }
- ChainDependency cd = chainDependencies.get(name);
- if (cd == null)
- {
- cd = new ChainDependency(name);
- chainDependencies.put(name, cd);
- }
- return cd;
+ /**
+ * Returns a {@code BeanProvider} for the local variable with the given
+ * name. Using this method, variables created during script execution can be
+ * accessed as beans and thus can act as providers for other tags.
+ *
+ * @param name the name of the local variable to be accessed (must not be
+ * <b>null</b>)
+ * @return a {@code BeanProvider} wrapping this local variable
+ * @throws IllegalArgumentException if the name is <b>null</b>
+ * @since 1.1
+ */
+ public BeanProvider getVariableBean(String name)
+ {
+ return fetchVariableDependency(name);
}
/**
* Returns a set with the names of the currently defined local variables.
- * These names can be passed to the <code>getVariable()</code> method for
+ * These names can be passed to the {@code getVariable()} method for
* querying the current values of these variables.
*
* @return a set with the names of the currently existing local variables
@@ -274,12 +282,12 @@
}
/**
- * Sets the value of the <code>clear variables</code> flag. If this flag
+ * Sets the value of the {@code clear variables} flag. If this flag
* is set to <b>true</b> (which is the default value), the storage for
* local variables is cleared at the beginning of an invocation. This
* ensures that values generated by earlier invocations do not affect the
* current invocation. If variables have been set manually using the
- * <code>setVariable()</code> method, it will be necessary to disable this
+ * {@code setVariable()} method, it will be necessary to disable this
* flag; otherwise these variables will also get lost.
*
* @param clearVariables the new value of the flag
@@ -290,9 +298,34 @@
}
/**
+ * Returns the name of the result variable.
+ *
+ * @return the name of the result variable
+ * @since 1.1
+ */
+ public String getResultVariableName()
+ {
+ return resultVariableName;
+ }
+
+ /**
+ * Sets the name of the result variable. If this property is set, the
+ * {@code invoke()} method will not return the passed in target object, but
+ * the object referenced by this variable. This is useful if the script
+ * generates a result.
+ *
+ * @param resultVariableName the name of the result variable
+ * @since 1.1
+ */
+ public void setResultVariableName(String resultVariableName)
+ {
+ this.resultVariableName = resultVariableName;
+ }
+
+ /**
* Returns a list of the dependencies required for this invocation. This
* implementation creates a union of the dependencies of all contained
- * <code>Invokable</code> objects.
+ * {@code Invokable} objects.
*
* @return a list with the dependencies
*/
@@ -308,7 +341,7 @@
/**
* Performs the invocation represented by this class. This implementation
- * will invoke all contained <code>Invokable</code> objects.
+ * will invoke all contained {@code Invokable} objects.
*
* @param depProvider the dependency provider
* @param target the target object
@@ -328,12 +361,12 @@
{
cid.performInvocation(depProvider, target);
}
- return target;
+ return fetchScriptResult(target);
}
/**
* Returns a string representation for this object. This implementation
- * outputs all contained <code>Invokable</code> objects.
+ * outputs all contained {@code Invokable} objects.
*
* @return a string for this object
*/
@@ -362,6 +395,45 @@
}
/**
+ * Returns the {@code ChainDependency} object for the specified variable.
+ *
+ * @param name the name of the variable (must not be <b>null</b>)
+ * @return the corresponding {@code ChainDependency} object
+ * @throws IllegalArgumentException if the variable name is <b>null</b>
+ */
+ private ChainDependency fetchVariableDependency(String name)
+ {
+ if (name == null)
+ {
+ throw new IllegalArgumentException(
+ "Variable name must not be null!");
+ }
+
+ ChainDependency cd = chainDependencies.get(name);
+ if (cd == null)
+ {
+ cd = new ChainDependency(name);
+ chainDependencies.put(name, cd);
+ }
+ return cd;
+ }
+
+ /**
+ * Determines the result of a script execution. This is per default the
+ * target object. If a result variable name has been specified, the value of
+ * this variable is returned.
+ *
+ * @param target the target of the script execution
+ * @return the result of the script execution
+ * @throws InjectionException if the variable cannot be found
+ */
+ private Object fetchScriptResult(Object target)
+ {
+ return (getResultVariableName() != null) ? getVariable(getResultVariableName())
+ : target;
+ }
+
+ /**
* A data class for storing the contained invocation objects. Instances of
* this class store all information required for executing an invocation.
*/
@@ -377,9 +449,9 @@
private String targetName;
/**
- * Creates a new instance of <code>ChainInvocationData</code>.
+ * Creates a new instance of {@code ChainInvocationData}.
*
- * @param inv the wrapped <code>Invokable</code> object
+ * @param inv the wrapped {@code Invokable} object
* @param result the name of the result variable
* @param target the name of the target variable
*/
@@ -391,9 +463,9 @@
}
/**
- * Returns the managed <code>Invokable</code> object.
+ * Returns the managed {@code Invokable} object.
*
- * @return the internal <code>Invokable</code> object
+ * @return the internal {@code Invokable} object
*/
public Invokable getInvokable()
{
@@ -424,7 +496,7 @@
}
/**
- * An internally used <code>Dependency</code> implementation for accessing
+ * An internally used {@code Dependency} implementation for accessing
* local variables. Instances of this class simply store the name of the
* desired local variable. The getBean() method is implemented by querying
* the map with the local variables.
@@ -435,7 +507,7 @@
private String varName;
/**
- * Creates a new instance of <code>ChainDependency</code> for the
+ * Creates a new instance of {@code ChainDependency} for the
* specified variable.
*
* @param var the name of the variable
@@ -448,7 +520,7 @@
/**
* Resolves this dependency. This implementation ignores all parameters
* and simply returns a pointer to itself. So the
- * <code>BeanProvider</code> implementation is used for querying the
+ * {@code BeanProvider} implementation is used for querying the
* managed bean.
*
* @param store the bean store
@@ -487,13 +559,13 @@
/**
* Returns the dependencies of this bean provider. This implementation
- * returns <b>null</b> because there are no dependencies.
+ * always returns an empty set because there are no dependencies.
*
* @return a set with the dependencies
*/
public Set<Dependency> getDependencies()
{
- return null;
+ return Collections.emptySet();
}
/**
Modified: trunk/core/src/main/java/net/sf/jguiraffe/di/impl/Invocation.java
===================================================================
--- trunk/core/src/main/java/net/sf/jguiraffe/di/impl/Invocation.java 2012-01-29 18:39:57 UTC (rev 206)
+++ trunk/core/src/main/java/net/sf/jguiraffe/di/impl/Invocation.java 2012-02-09 07:30:13 UTC (rev 207)
@@ -30,10 +30,10 @@
* invoking a method using reflection. Especially the parameter types and the
* parameter values can be specified. The parameter values are provided as
* {@link Dependency} objects, so they can refer to other beans defined in a
- * <code>BeanStore</code>.
+ * {@code BeanStore}.
* </p>
* <p>
- * The main use case for <code>Invocation</code> objects is the creation and
+ * The main use case for {@code Invocation} objects is the creation and
* initialization of beans performed by the dependency injection framework: At
* first a bean has to be created by invoking one of its constructors. After
* that some initialization methods may be called. In both cases the parameters
@@ -64,7 +64,7 @@
private final ClassDescription targetClass;
/**
- * Creates a new instance of <code>Invocation</code> and initializes it
+ * Creates a new instance of {@code Invocation} and initializes it
* with information about the call parameters. To perform an invocation the
* class has to know the current parameter values and (at least partly) the
* data types of these values. From this information the signature of the
@@ -78,7 +78,7 @@
* invoked
* @param paramTypes an array with the parameter type descriptions
* @param paramValues the current parameter values (defined as
- * <code>Dependency</code> objects); this array must not contain <b>null</b>
+ * {@code Dependency} objects); this array must not contain <b>null</b>
* elements
* @throws IllegalArgumentException if the length of the parameter types
* array does not match the length of the parameter values array or if the
@@ -119,10 +119,10 @@
}
/**
- * Returns the <code>Dependency</code> objects defining the current
+ * Returns the {@code Dependency} objects defining the current
* parameter values.
*
- * @return a list with the <code>Dependency</code> objects for the
+ * @return a list with the {@code Dependency} objects for the
* parameter values
*/
public List<Dependency> getParameterDependencies()
@@ -154,7 +154,7 @@
/**
* Returns an array with the resolved parameters. This method iterates over
* the parameter dependencies and tries to resolve them using the specified
- * <code>DependencyProvider</code>. An array with the resulting beans is
+ * {@code DependencyProvider}. An array with the resulting beans is
* returned. If no parameters are specified (i.e. for invocations of methods
* that do not have arguments), the return value is <b>null</b>.
*
@@ -171,11 +171,7 @@
{
return null;
}
- if (depProvider == null)
- {
- throw new IllegalArgumentException(
- "Dependency provider must not be null!");
- }
+ checkDependencyProvider(depProvider);
Object[] values = new Object[parameterDependencies.size()];
int idx = 0;
@@ -188,8 +184,8 @@
/**
* Returns an array with the concrete parameter classes. This method
- * converts the internally stored <code>ClassDescription</code> objects into
- * <code>Class</code> objects.
+ * converts the internally stored {@code ClassDescription} objects into
+ * {@code Class} objects.
*
* @param depProvider the dependency provider for resolving the classes
* @return an array with the parameter classes
@@ -217,8 +213,8 @@
* target class name, the parameters, and further information provided by
* sub classes). This implementation will print the concrete class name,
* followed by an opening square bracket. Then
- * <code>invocationInfoToString()</code>, and
- * <code>parametersToString()</code> are called. Finally a closing square
+ * {@code invocationInfoToString()}, and
+ * {@code parametersToString()} are called. Finally a closing square
* bracket is output.
*
* @return a string for this object
@@ -238,7 +234,7 @@
/**
* Creates a string with additional information about this invocation. This
- * method is called by the default <code>toString()</code> implementation.
+ * method is called by the default {@code toString()} implementation.
* It adds the target class to the buffer if it is defined.
*
* @param buf the target buffer
@@ -254,8 +250,8 @@
/**
* Creates a string representation of the current parameter values. This
* implementation iterates over all parameter dependencies and invokes their
- * <code>toString()</code> method. It is called by the
- * <code>toString()</code> method.
+ * {@code toString()} method. It is called by the
+ * {@code toString()} method.
*
* @param buf the target buffer
*/
@@ -279,6 +275,23 @@
}
/**
+ * Checks whether a valid {@code DependencyProvider} has been specified.
+ *
+ * @param depProvider the provider to be checked
+ * @throws IllegalArgumentException if the {@code DependencyProvider} is
+ * undefined
+ * @since 1.1
+ */
+ protected static void checkDependencyProvider(DependencyProvider depProvider)
+ {
+ if (depProvider == null)
+ {
+ throw new IllegalArgumentException(
+ "Dependency provider must not be null!");
+ }
+ }
+
+ /**
* Initializes the array with the parameter types. <b>null</b> may have
* been passed in, which has to be converted to a valid value.
*
Modified: trunk/core/src/main/java/net/sf/jguiraffe/di/impl/MethodInvocation.java
===================================================================
--- trunk/core/src/main/java/net/sf/jguiraffe/di/impl/MethodInvocation.java 2012-01-29 18:39:57 UTC (rev 206)
+++ trunk/core/src/main/java/net/sf/jguiraffe/di/impl/MethodInvocation.java 2012-02-09 07:30:13 UTC (rev 207)
@@ -15,6 +15,10 @@
*/
package net.sf.jguiraffe.di.impl;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
import net.sf.jguiraffe.di.Dependency;
import net.sf.jguiraffe.di.DependencyProvider;
import net.sf.jguiraffe.di.InjectionException;
@@ -32,7 +36,7 @@
* <p>
* Once initialized, an instance is immutable. So it can easily be shared
* between multiple components and threads without having to care about
- * synchronization issues. The <code>invoke()</code> method actually executes
+ * synchronization issues. The {@code invoke()} method actually executes
* the corresponding method.
* </p>
*
@@ -41,6 +45,9 @@
*/
public class MethodInvocation extends Invocation implements Invokable
{
+ /** Stores the target dependency for this invocation. */
+ private final Dependency targetDependency;
+
/** Stores the name of the method to invoke. */
private final String methodName;
@@ -48,7 +55,7 @@
private final boolean staticInvocation;
/**
- * Creates a new instance of <code>MethodInvocation</code> for non-static
+ * Creates a new instance of {@code MethodInvocation} for non-static
* method invocations. This constructor sets the target class to <b>null</b>,
* so that it can only be derived from the target instance (which prohibits
* static method invocations).
@@ -57,7 +64,7 @@
* <b>null</b>)
* @param paramTypes an array with the parameter types
* @param paramValues the current parameter values (defined as
- * <code>Dependency</code> objects); this array must not contain <b>null</b>
+ * {@code Dependency} objects); this array must not contain <b>null</b>
* elements
* @throws IllegalArgumentException if the length of the parameter types
* array does not match the length of the parameter values array, or if the
@@ -71,7 +78,7 @@
}
/**
- * Creates a new instance of <code>MethodInvocation</code> and initializes
+ * Creates a new instance of {@code MethodInvocation} and initializes
* it with information about the method to invoke and the target class.
*
* @param targetClass the class, on which the method is to be invoked
@@ -79,7 +86,7 @@
* <b>null</b>)
* @param paramTypes an array with the parameter types
* @param paramValues the current parameter values (defined as
- * <code>Dependency</code> objects); this array must not contain <b>null</b>
+ * {@code Dependency} objects); this array must not contain <b>null</b>
* elements
* @throws IllegalArgumentException if the length of the parameter types
* array does not match the length of the parameter values array, or if the
@@ -94,10 +101,10 @@
}
/**
- * Creates a new instance of <code>MethodInvocation</code> and fully
- * initializes it. This constructor takes all information required for
- * arbitrary method invocations. Refer to the base class for a detailed
- * explanation of the arguments.
+ * Creates a new instance of {@code MethodInvocation} and initializes most
+ * of the properties. This constructor is appropriate for static or
+ * non-static invocations which are performed on the target object passed to
+ * the {@code invoke()} method.
*
* @param targetClass the class, on which the method is to be invoked
* @param methodName the name of the method to be invoked (must not be
@@ -105,7 +112,7 @@
* @param isStatic determines whether a static method is to be invoked
* @param paramTypes an array with the parameter types
* @param paramValues the current parameter values (defined as
- * <code>Dependency</code> objects); this array must not contain <b>null</b>
+ * {@code Dependency} objects); this array must not contain <b>null</b>
* elements
* @throws IllegalArgumentException if the length of the parameter types
* array does not match the length of the parameter values array, or if the
@@ -118,6 +125,39 @@
boolean isStatic, ClassDescription[] paramTypes,
Dependency... paramValues)
{
+ this(targetClass, null, methodName, isStatic, paramTypes, paramValues);
+ }
+
+ /**
+ * Creates a new instance of {@code MethodInvocation} and fully initializes
+ * it. This constructor takes all information required for arbitrary method
+ * invocations. It is especially possible to define a dependency for the
+ * target object. If set, this dependency is resolved during invocation; a
+ * target object is then ignored. Refer to the base class for a detailed
+ * explanation of the arguments.
+ *
+ * @param targetClass the class, on which the method is to be invoked
+ * @param targetDep an optional {@code Dependency} to the target bean on
+ * which the method should be invoked
+ * @param methodName the name of the method to be invoked (must not be
+ * <b>null</b>)
+ * @param isStatic determines whether a static method is to be invoked
+ * @param paramTypes an array with the parameter types
+ * @param paramValues the current parameter values (defined as
+ * {@code Dependency} objects); this array must not contain
+ * <b>null</b> elements
+ * @throws IllegalArgumentException if the length of the parameter types
+ * array does not match the length of the parameter values array, or
+ * if the values array contains <b>null</b> elements, or if the
+ * method name is undefined, or if the static flag is <b>true</b>,
+ * but no target class is defined
+ * @see Invocation#Invocation(Class, Class[], Dependency...)
+ * @since 1.1
+ */
+ public MethodInvocation(ClassDescription targetClass, Dependency targetDep,
+ String methodName, boolean isStatic, ClassDescription[] paramTypes,
+ Dependency... paramValues)
+ {
super(targetClass, paramTypes, paramValues);
if (methodName == null)
{
@@ -129,6 +169,7 @@
"Need a target class for a static invocation!");
}
+ targetDependency = targetDep;
this.methodName = methodName;
staticInvocation = isStatic;
}
@@ -155,31 +196,66 @@
}
/**
+ * Returns the target {@code Dependency} of this {@code MethodInvocation}.
+ * This dependency defines the bean on which the method is to be invoked. If
+ * there is no target dependency, result is <b>null</b>.
+ *
+ * @return the target {@code Dependency}
+ * @since 1.1
+ */
+ public Dependency getTargetDependency()
+ {
+ return targetDependency;
+ }
+
+ /**
+ * {@inheritDoc} This implementation adds the dependency to the invocation
+ * target if it exists.
+ */
+ @Override
+ public List<Dependency> getParameterDependencies()
+ {
+ List<Dependency> deps = super.getParameterDependencies();
+ Dependency depTarget = getTargetDependency();
+ if (depTarget == null)
+ {
+ return deps;
+ }
+
+ List<Dependency> result = new ArrayList<Dependency>(deps.size() + 1);
+ result.addAll(deps);
+ result.add(depTarget);
+ return Collections.unmodifiableList(result);
+ }
+
+ /**
* Invokes the corresponding method on the specified target instance. The
* method's result is returned. The behavior of this method depends on the
- * {@link #isStaticInvocation()} flag. If it is set, a passed
- * in target object is ignored and a static method invocation on the target
- * class is performed. Otherwise, if a non <b>null</b> target object is
- * passed in, the target class is derived from this instance (an eventually
- * set target class is ignored).
+ * {@link #isStaticInvocation()} flag. If it is set, a passed in target
+ * object is ignored and a static method invocation on the target class is
+ * performed. Otherwise, if a non <b>null</b> target object is passed in,
+ * the target class is derived from this instance (an eventually set target
+ * class is ignored).
*
* @param depProvider the dependency provider for resolving the parameters
- * (must not be <b>null</b>)
+ * (must not be <b>null</b>)
* @param target the target instance, on which to invoke the method
* @return the method's return value
* @throws InjectionException in case of an error
- * @throws IllegalArgumentException if the dependency provider is <b>null</b>
+ * @throws IllegalArgumentException if the dependency provider is
+ * <b>null</b>
*/
public Object invoke(DependencyProvider depProvider, Object target)
{
- if (target == null && getTargetClass() == null)
+ Object targetObject = resolveTarget(depProvider, target);
+ if (targetObject == null && getTargetClass() == null)
{
throw new InjectionException(
"Target class and instance must not both be null!");
}
Object[] values = getResolvedParameters(depProvider);
- if (isStaticInvocation() || target == null)
+ if (isStaticInvocation() || targetObject == null)
{
return depProvider.getInvocationHelper().invokeStaticMethod(
getTargetClass().getTargetClass(depProvider),
@@ -188,8 +264,8 @@
else
{
return depProvider.getInvocationHelper().invokeInstanceMethod(
- target, getMethodName(), getParameterClasses(depProvider),
- values);
+ targetObject, getMethodName(),
+ getParameterClasses(depProvider), values);
}
}
@@ -209,4 +285,27 @@
}
buf.append(getMethodName());
}
+
+ /**
+ * Resolves the target object of this method invocation. If a target
+ * dependency is set, it is resolved, and the resulting object is used as
+ * target.
+ *
+ * @param depProvider the {@code DependencyProvider}
+ * @param target the target object passed to {@code invoke()}
+ * @return the target object of the invocation
+ * @throws IllegalArgumentException if the {@code DependencyProvider} is
+ * <b>null</b>
+ */
+ private Object resolveTarget(DependencyProvider depProvider, Object target)
+ {
+ Dependency dep = getTargetDependency();
+ if (dep == null)
+ {
+ return target;
+ }
+
+ checkDependencyProvider(depProvider);
+ return depProvider.getDependentBean(dep);
+ }
}
Modified: trunk/core/src/main/java/net/sf/jguiraffe/di/impl/NullInvocation.java
===================================================================
--- trunk/core/src/main/java/net/sf/jguiraffe/di/impl/NullInvocation.java 2012-01-29 18:39:57 UTC (rev 206)
+++ trunk/core/src/main/java/net/sf/jguiraffe/di/impl/NullInvocation.java 2012-02-09 07:30:13 UTC (rev 207)
@@ -20,6 +20,7 @@
import net.sf.jguiraffe.di.Dependency;
import net.sf.jguiraffe.di.DependencyProvider;
+import net.sf.jguiraffe.di.impl.providers.HelperInvocations;
/**
* <p>
@@ -36,7 +37,11 @@
*
* @author Oliver Heger
* @version $Id$
+ * @deprecated Use {@link HelperInvocations} instead; it provides some dummy
+ * implementations of the {@code Invokable} interface which are useful in some
+ * situations where a full-blown implementation is not required.
*/
+@Deprecated
public final class NullInvocation implements Invokable
{
/** The default instance of this class. */
Added: trunk/core/src/main/java/net/sf/jguiraffe/di/impl/providers/HelperInvocations.java
===================================================================
--- trunk/core/src/main/java/net/sf/jguiraffe/di/impl/providers/HelperInvocations.java (rev 0)
+++ trunk/core/src/main/java/net/sf/jguiraffe/di/impl/providers/HelperInvocations.java 2012-02-09 07:30:13 UTC (rev 207)
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2006-2012 The JGUIraffe Team.
+ *
+ * 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 net.sf.jguiraffe.di.impl.providers;
+
+import java.util.Collections;
+import java.util.List;
+
+import net.sf.jguiraffe.di.Dependency;
+import net.sf.jguiraffe.di.DependencyProvider;
+import net.sf.jguiraffe.di.impl.Invokable;
+
+/**
+ * <p>
+ * An enumeration class defining some simple helper {@code Invokable}
+ * implementations.
+ * </p>
+ * <p>
+ * There are cases where an {@code Invokable} is needed, but no concrete value
+ * object is available. For instance, when creating a bean an initializer script
+ * may be supported, but it is optional. This enumeration class provides helper
+ * objects which can be used for optional invocations rather than doing
+ * <b>null</b> checks all the time. So this is an application of the <em>null
+ * object pattern</em>.
+ * </p>
+ * <p>
+ * The constants defined by this class are dummy implementations which do not
+ * actually perform any meaningful action. They differ in the values returned by
+ * their implementation of the {@code invoke()} method. Because these
+ * implementations are state-less, they can be defined as enumeration constants
+ * and shared between all interested parties.
+ * </p>
+ *
+ * @author Oliver Heger
+ * @version $Id$
+ * @since 1.1
+ */
+public enum HelperInvocations implements Invokable
+{
+ /**
+ * A specialized {@code Invokable} implementation which always returns
+ * <b>null</b> in its {@code invoke()} implementation.
+ */
+ NULL_INVOCATION
+ {
+ public Object invoke(DependencyProvider depProvider, Object target)
+ {
+ return null;
+ }
+ },
+
+ /**
+ * An implementation of {@code Invokable} which realizes an identity
+ * invocation. It always returns the object passed in as invocation target
+ * without any further modifications.
+ */
+ IDENTITY_INVOCATION
+ {
+ public Object invoke(DependencyProvider depProvider, Object target)
+ {
+ return target;
+ }
+ };
+
+ /**
+ * Returns the dependencies for this invocation. This implementation always
+ * returns an empty list.
+ *
+ * @return the dependencies of this {@code Invokable}
+ */
+ public List<Dependency> getParameterDependencies()
+ {
+ return Collections.emptyList();
+ }
+}
Property changes on: trunk/core/src/main/java/net/sf/jguiraffe/di/impl/providers/HelperInvocations.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Author Id Revision HeadURL
Added: svn:eol-style
+ native
Modified: trunk/core/src/main/java/net/sf/jguiraffe/di/impl/providers/LifeCycleBeanProvider.java
===================================================================
--- trunk/core/src/main/java/net/sf/jguiraffe/di/impl/providers/LifeCycleBeanProvider.java 2012-01-29 18:39:57 UTC (rev 206)
+++ trunk/core/src/main/java/net/sf/jguiraffe/di/impl/providers/LifeCycleBeanProvider.java 2012-02-09 07:30:13 UTC (rev 207)
@@ -27,15 +27,14 @@
import net.sf.jguiraffe.di.InjectionException;
import net.sf.jguiraffe.di.InvocationHelper;
import net.sf.jguiraffe.di.impl.Invokable;
-import net.sf.jguiraffe.di.impl.NullInvocation;
/**
* <p>
- * An abstract base class for <code>BeanProvider</code> implementations with
+ * An abstract base class for {@code BeanProvider} implementations with
* life-cycle support.
* </p>
* <p>
- * A <code>LifeCycleBeanProvider</code> has the following properties:
+ * A {@code LifeCycleBeanProvider} has the following properties:
* <ul>
* <li>A (usually simple) {@link BeanProvider} for actually
* creating an instance of the managed bean.</li>
@@ -46,32 +45,32 @@
* <p>
* This base class provides basic functionality for the creation and
* initialization of beans. It also implements the methods related to life-cycle
- * support of the <code>BeanProvider</code> interface in a meaningful way.
+ * support of the {@code BeanProvider} interface in a meaningful way.
* There are two methods that are intended to be called by concrete sub classes:
- * <code>createBean()</code> and <code>fetchBean()</code>.
+ * {@code createBean()} and {@code fetchBean()}.
* </p>
* <p>
- * <code>createBean()</code>, as its name implies, creates a new instance of
+ * {@code createBean()}, as its name implies, creates a new instance of
* the managed bean class. This is done by invoking the
- * <code>BeanProvider</code> for creating new beans. After that the
- * <code>Invokable</code> object is called on the newly created bean. The
+ * {@code BeanProvider} for creating new beans. After that the
+ * {@code Invokable} object is called on the newly created bean. The
* creation of a bean through the bean provider may cause an endless loop if
* there are cyclic dependencies (e.g. bean A needs bean B as a constructor
* argument and vice verse). Such cycles are detected and lead to a
- * <code>InjectionException</code> exception being thrown.
+ * {@code InjectionException} exception being thrown.
* </p>
* <p>
- * The <code>fetchBean()</code> method checks whether a bean instance has
+ * The {@code fetchBean()} method checks whether a bean instance has
* already been created. If this is the case, it is directly returned. Otherwise
- * <code>createBean()</code> is called for creating a new instance. Depending
+ * {@code createBean()} is called for creating a new instance. Depending
* on their semantics derived classes decide, which of these methods to call.
- * This decision must be implemented in the <code>getBean()</code> method; all
- * other methods defined by the <code>BeanProvider</code> interface are
+ * This decision must be implemented in the {@code getBean()} method; all
+ * other methods defined by the {@code BeanProvider} interface are
* already implemented by this base class.
* </p>
* <p>
* Implementation note: This class is intended to be used together with a
- * correct implementation of the <code>BeanContext</code> interface. It is not
+ * correct implementation of the {@code BeanContext} interface. It is not
* thread-safe by itself, but if the bean context handles transactions properly,
* it can be used in an environment with multiple threads accessing the bean
* context concurrently.
@@ -112,9 +111,9 @@
private volatile boolean instanceCreated;
/**
- * Creates a new instance of <code>LifeCycleBeanProvider</code> and
- * initializes it with the <code>BeanProvider</code> for creating the bean
- * instance and an <code>Invokable</code> for initializing it.
+ * Creates a new instance of {@code LifeCycleBeanProvider} and
+ * initializes it with the {@code BeanProvider} for creating the bean
+ * instance and an {@code Invokable} for initializing it.
*
* @param createProvider the bean provider for creating a bean instance
* (must not be <b>null</b>)
@@ -131,12 +130,14 @@
"Creation bean provider must not be null!");
}
beanCreator = createProvider;
- beanInitializer = (initinv != null) ? initinv : NullInvocation.INSTANCE;
+ beanInitializer =
+ (initinv != null) ? initinv
+ : HelperInvocations.IDENTITY_INVOCATION;
}
/**
- * Creates a new instance of <code>LifeCycleBeanProvider</code> and
- * initializes it with the <code>BeanProvider</code> for creating the bean
+ * Creates a new instance of {@code LifeCycleBeanProvider} and
+ * initializes it with the {@code BeanProvider} for creating the bean
* instance.
*
* @param createProvider the bean provider for creating a bean instance
@@ -149,7 +150,7 @@
}
/**
- * Returns the <code>BeanProvider</code> that is responsible for creating
+ * Returns the {@code BeanProvider} that is responsible for creating
* a new bean instance.
*
* @return the bean provider for creating new bean instances
@@ -160,7 +161,7 @@
}
/**
- * Returns the <code>Invokable</code> object responsible for initializing
+ * Returns the {@code Invokable} object responsible for initializing
* the newly created bean. This method never returns <b>null</b>. If no
* initializer was set, a default initializer object (that does not have any
* effect) is returned.
@@ -174,7 +175,7 @@
/**
* Returns the class of the bean managed by this provider. This class is
- * determined by the <code>BeanProvider</code> for creating new bean
+ * determined by the {@code BeanProvider} for creating new bean
* instances.
*
* @param dependencyProvider the dependency provider
@@ -195,15 +196,21 @@
*/
public Set<Dependency> getDependencies()
{
- List<Dependency> initDeps = getBeanInitializer().getParameterDependencies();
+ List<Dependency> initDeps =
+ getBeanInitializer().getParameterDependencies();
+ Set<Dependency> creatorDeps = getBeanCreator().getDependencies();
+
if (initDeps.isEmpty())
{
- return getBeanCreator().getDependencies();
+ return creatorDeps;
}
else
{
Set<Dependency> result = new HashSet<Dependency>();
- result.addAll(getBeanCreator().getDependencies());
+ if (creatorDeps != null)
+ {
+ result.addAll(creatorDeps);
+ }
result.addAll(initDeps);
return result;
}
@@ -266,7 +273,9 @@
{
try
{
- initBean(bean, dependencyProvider);
+ Object initBean =
+ fetchInitializedBeanInstance(bean, dependencyProvider);
+ bean = initBean;
instanceCreated = true;
}
finally
@@ -328,7 +337,9 @@
canInit = canInitialize(dependencyProvider);
if (canInit)
{
- initBean(bean, dependencyProvider);
+ bean =
+ fetchInitializedBeanInstance(bean,
+ dependencyProvider);
}
else
{
@@ -356,7 +367,7 @@
/**
* Returns the bean instance created by this provider. If no instance has
- * been created yet, this is done now by invoking <code>createBean()</code>.
+ * been created yet, this is done now by invoking {@code createBean()}.
* Otherwise the bean instance is directly returned. If the dependencies
* contain cyclic references, it is possible that a bean instance is
* returned, which has not yet been fully initialized. Cycles that cannot be
@@ -412,7 +423,7 @@
/**
* Resets any so far created bean. This method can be called by derived
* classes to reset this bean provider. In a following call to
- * <code>fetchBean()</code> a completely new bean will be created.
+ * {@code fetchBean()} a completely new bean will be created.
*/
protected void resetBean()
{
@@ -422,7 +433,7 @@
/**
* Creates a new bean instance. This method is called by
- * <code>createBean()</code> for actually creating the bean.
+ * {@code createBean()} for actually creating the bean.
*
* @param dependencyProvider the dependency provider
* @return the new bean instance
@@ -443,7 +454,11 @@
* @param bean the bean to initialize
* @param dependencyProvider the dependency provider
* @throws InjectionException if an error occurs
+ * @deprecated This method is not called any more during bean creation;
+ * instead {@link #fetchInitializedBeanInstance(Object, DependencyProvider)}
+ * is invoked
*/
+ @Deprecated
protected void initBean(Object bean, DependencyProvider dependencyProvider)
{
getBeanInitializer().invoke(dependencyProvider, bean);
@@ -451,9 +466,34 @@
}
/**
+ * Returns the initialized bean instance. This method is called by
+ * {@code createBean()} for each new bean instance. Its purpose is to
+ * execute the initializer script on the bean. This implementation invokes
+ * the initializer and notifies the {@code DependencyProvider} about the
+ * creation of a new bean. Note that the bean returned by the initializer
+ * script is the result of this method. Thus it is possible that a different
+ * bean than passed to the method becomes the managed bean of this provider.
+ * However, if the initializer returns <b>null</b>, the passed in bean is
+ * returned.
+ *
+ * @param bean the bean to initialize
+ * @param dependencyProvider the dependency provider
+ * @return the bean instance
+ * @throws InjectionException if an error occurs
+ * @since 1.1
+ */
+ protected Object fetchInitializedBeanInstance(Object bean,
+ DependencyProvider dependencyProvider)
+ {
+ Object initBean = getBeanInitializer().invoke(dependencyProvider, bean);
+ dependencyProvider.beanCreated(initBean, this);
+ return (initBean != null) ? initBean : bean;
+ }
+
+ /**
* Creates a specialized dependency provider with the ability of generating
* meaningful error messages in case of cyclic dependencies. This method is
- * called by <code>createBean()</code> before the creator is invoked.
+ * called by {@code createBean()} before the creator is invoked.
*
* @param wrappedProvider the dependency provider to be wrapped
* @return the diagnostic dependency provider
@@ -465,10 +505,10 @@
}
/**
- * A specialized <code>DependencyProvider</code> implementation that is
+ * A specialized {@code DependencyProvider} implementation that is
* used for generating meaningful error messages for cyclic dependencies.
* This implementation stores the currently processed dependency in a member
- * field. If later a reentrant call to <code>createBean()</code> happens,
+ * field. If later a reentrant call to {@code createBean()} happens,
* we are able to determine, which dependency caused the problem.
*/
private class DiagnosticDependencyProvider implements DependencyProvider
@@ -477,7 +517,7 @@
private final DependencyProvider wrappedProvider;
/**
- * Creates a new instance of <code>DiagnosticDependencyProvider</code>
+ * Creates a new instance of {@code DiagnosticDependencyProvider}
* and sets the dependency provider to be wrapped.
*
* @param d the wrapped dependency provider
Modified: trunk/core/src/main/java/net/sf/jguiraffe/di/impl/providers/SingletonBeanProvider.java
===================================================================
--- trunk/core/src/main/java/net/sf/jguiraffe/di/impl/providers/SingletonBeanProvider.java 2012-01-29 18:39:57 UTC (rev 206)
+++ trunk/core/src/main/java/net/sf/jguiraffe/di/impl/providers/SingletonBeanProvider.java 2012-02-09 07:30:13 UTC (rev 207)
@@ -21,7 +21,6 @@
import net.sf.jguiraffe.di.Dependency;
import net.sf.jguiraffe.di.DependencyProvider;
import net.sf.jguiraffe.di.impl.Invokable;
-import net.sf.jguiraffe.di.impl.NullInvocation;
/**
* <p>
@@ -76,7 +75,7 @@
}
/**
- * Creates a new instance of <code>SingletonBeanProvider</code> and
+ * Creates a new instance of {@code SingletonBeanProvider} and
* initializes it with the bean provider for creating a bean instance and
* the invocation object for performing initialization.
*
@@ -93,7 +92,7 @@
}
/**
- * Creates a new instance of <code>SingletonBeanProvider</code> and
+ * Creates a new instance of {@code SingletonBeanProvider} and
* initializes it with the bean provider for creating a bean instance.
*
* @param createProvider the bean provider used for creating a new bean
@@ -183,6 +182,6 @@
Invokable fetchShutdownInvokable()
{
return (getShutdownHandler() != null) ? getShutdownHandler()
- : NullInvocation.INSTANCE;
+ : HelperInvocations.NULL_INVOCATION;
}
}
Modified: trunk/core/src/main/java/net/sf/jguiraffe/gui/builder/di/tags/BeanTag.java
===================================================================
--- trunk/core/src/main/java/net/sf/jguiraffe/gui/builder/di/tags/BeanTag.java 2012-01-29 18:39:57 UTC (rev 206)
+++ trunk/core/src/main/java/net/sf/jguiraffe/gui/builder/di/tags/BeanTag.java 2012-02-09 07:30:13 UTC (rev 207)
@@ -16,6 +16,7 @@
package net.sf.jguiraffe.gui.builder.di.tags;
import net.sf.jguiraffe.di.BeanProvider;
+import net.sf.jguiraffe.di.DependencyProvider;
import net.sf.jguiraffe.di.impl.ChainedInvocation;
import net.sf.jguiraffe.di.impl.ClassDescription;
import net.sf.jguiraffe.di.impl.ConstructorInvocation;
@@ -24,6 +25,7 @@
import net.sf.jguiraffe.di.impl.providers.ConstantBeanProvider;
import net.sf.jguiraffe.di.impl.providers.ConstructorBeanProvider;
import net.sf.jguiraffe.di.impl.providers.FactoryBeanProvider;
+import net.sf.jguiraffe.di.impl.providers.SimpleBeanProvider;
import net.sf.jguiraffe.di.impl.providers.SingletonBeanProvider;
import org.apache.commons.jelly.JellyTagException;
@@ -45,7 +47,7 @@
* </pre>
*
* </li>
- * <li>With the <code>store</code> attribute the name of the
+ * <li>With the {@code store} attribute the name of the
* {@link net.sf.jguiraffe.di.BeanStore BeanStore}, in which the constructed
* {@link BeanProvider} is stored, can be specified:
*
@@ -74,7 +76,7 @@
* </pre>
*
* </li>
- * <li>The <code>singleton</code> attribute has impact on the way the bean is
+ * <li>The {@code singleton} attribute has impact on the way the bean is
* created. If set to <b>true</b> (which is the default), only a single bean
* instance will be created on first access. Further access to this bean
* definition will always return the same bean. A value of <b>false</b> in
@@ -104,7 +106,7 @@
* for singleton beans. If each access to the bean creates a new instance, the
* caller is responsible for releasing the bean instances correspondingly.</li>
* <li>If a different constructor than the default one is to be used, a nested
- * <code>{@link ConstructorTag}</code> tag can be used. Here the parameters to
+ * {@link ConstructorTag} tag can be used. Here the parameters to
* be passed to the constructor can be defined:
*
* <pre>
@@ -120,7 +122,7 @@
*
* </li>
* <li>If the bean cannot be created directly, but a factory has to be used, a
- * nested <code>{@link FactoryTag}</code> is appropriate. This can look as
+ * nested {@link FactoryTag} is appropriate. This can look as
* follows:
*
* <pre>
@@ -138,7 +140,7 @@
* </pre>
*
* </li>
- * <li>It is also possible to use a <code><bean></code> tag everywhere a
+ * <li>It is also possible to use a {@code <bean>} tag everywhere a
* dependency is expected. This allows defining beans in-line as in the
* following example:
*
@@ -155,14 +157,14 @@
* </bean>
* </pre>
*
- * Here the value of the first <code><param></code> tag is the bean
- * defined by the nested <code><bean></code> tag. This is a bit similar to
+ * Here the value of the first {@code <param>} tag is the bean
+ * defined by the nested {@code <bean>} tag. This is a bit similar to
* anonymous inner classes in Java. The result is effectively the same as if the
* bean was defined elsewhere with a specific name and the
- * <code><param></code> tag would reference this bean.</li>
+ * {@code <param>} tag would reference this bean.</li>
* <li>No matter of how the bean is created, in the tag's body an arbitrary
* number of <em>invocation tags</em> can be placed. These are collected and
- * added to a <code>{@link ChainedInvocation}</code> object, so that they form
+ * added to a {@link ChainedInvocation} object, so that they form
* an initialization script. This script will be executed after the bean
* instance has been created:
*
@@ -213,7 +215,7 @@
* </tr>
* <tr>
* <td valign="top">valueClassName</td>
- * <td>Like <code>valueClass</code>, but the name of the property's data type
+ * <td>Like {@code valueClass}, but the name of the property's data type
* class is specified.</td>
* <td valign="top">yes</td>
* </tr>
@@ -231,7 +233,7 @@
* <td valign="top">yes</td> </tr>
* <tr>
* <td valign="top">beanClassName</td>
- * <td>Like the <code>beanClass</code> attribute, but the bean class is
+ * <td>Like the {@code beanClass} attribute, but the bean class is
* specified by its name.</td>
* <td valign="top">yes</td>
* </tr>
@@ -259,6 +261,17 @@
* the root bean store of the current builder operation is used.</td>
* <td valign="top">yes</td>
* </tr>
+ * <tr>
+ * <td valign="top">resultVar</td>
+ * <td>This attribute provides an alternative way of defining a bean: as a result
+ * variable of an initializer script. When the initializer script is executed
+ * local variables can be created. The {@code resultVar} attribute instructs
+ * the tag to use one of these variables as the bean to be returned. With this
+ * mechanism, it is possible for instance to invoke a factory bean and return
+ * the object created by it. Note that the {@code resultVar} attribute takes
+ * precedence over other mechanisms to define the resulting bean.</td>
+ * <td valign="top">yes</td>
+ * </tr>
* </table>
* </p>
*
@@ -267,6 +280,10 @@
*/
public class BeanTag extends AbstractBeanTag
{
+ /** Constant for the string pattern for the place holder bean provider. */
+ private static final String PLACE_HOLDER_PROVIDER_STR =
+ "<Place holder for bean of class %s>";
+
/** Stores the bean provider for creating the managed bean. */
private BeanProvider beanCreator;
@@ -295,12 +312,13 @@
private boolean singleton;
/**
- * Creates a new instance of <code>BeanTag</code>.
+ * Creates a new instance of {@code BeanTag}.
*/
public BeanTag()
{
valueData = new ValueData(this);
beanClassData = new ClassDescData();
+ initializerScript = new ChainedInvocation();
setSingleton(true);
}
@@ -339,7 +357,7 @@
* Sets the class description for the managed bean. Usually, this method
* will be called by the main processing method when the tag's attributes
* are evaluated. If the bean class is not defined by the tag's attributes,
- * it can be indirectly defined by the <code>BeanProvider</code> used as
+ * it can be indirectly defined by the {@code BeanProvider} used as
* creator.
*
* @param beanClass the class description for the managed bean
@@ -350,10 +368,10 @@
}
/**
- * Returns the <code>BeanProvider</code> that will be used for creating
+ * Returns the {@code BeanProvider} tha...
[truncated message content] |