KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > beans > factory > config > MethodInvokingFactoryBean


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.beans.factory.config;
18
19 import java.lang.reflect.InvocationTargetException JavaDoc;
20 import java.lang.reflect.Method JavaDoc;
21
22 import org.springframework.beans.TypeConverter;
23 import org.springframework.beans.factory.BeanClassLoaderAware;
24 import org.springframework.beans.factory.BeanFactory;
25 import org.springframework.beans.factory.BeanFactoryAware;
26 import org.springframework.beans.factory.FactoryBean;
27 import org.springframework.beans.factory.FactoryBeanNotInitializedException;
28 import org.springframework.beans.factory.InitializingBean;
29 import org.springframework.beans.support.ArgumentConvertingMethodInvoker;
30 import org.springframework.util.ClassUtils;
31
32 /**
33  * FactoryBean which returns a value which is the result of a static or instance
34  * method invocation. For most use cases it is better to just use the container's
35  * built-in factory method support for the same purpose, since that is smarter at
36  * converting arguments. This factory bean is still useful though when you need to
37  * call a method which doesn't return any value (for example, a static class method
38  * to force some sort of initialization to happen). This use case is not supported
39  * by factory methods, since a return value is needed to obtain the bean instance.
40  *
41  * <p>Note that as it is expected to be used mostly for accessing factory methods,
42  * this factory by default operates in a <b>singleton</b> fashion. The first request
43  * to {@link #getObject} by the owning bean factory will cause a method invocation,
44  * whose return value will be cached for subsequent requests. An internal
45  * {@link #setSingleton singleton} property may be set to "false", to cause this
46  * factory to invoke the target method each time it is asked for an object.
47  *
48  * <p>A static target method may be specified by setting the
49  * {@link #setTargetMethod targetMethod} property to a String representing the static
50  * method name, with {@link #setTargetClass targetClass} specifying the Class that
51  * the static method is defined on. Alternatively, a target instance method may be
52  * specified, by setting the {@link #setTargetObject targetObject} property as the target
53  * object, and the {@link #setTargetMethod targetMethod} property as the name of the
54  * method to call on that target object. Arguments for the method invocation may be
55  * specified by setting the {@link #setArguments arguments} property.
56  *
57  * <p>This class depends on {@link #afterPropertiesSet()} being called once
58  * all properties have been set, as per the InitializingBean contract.
59  *
60  * <p>An example (in an XML based bean factory definition) of a bean definition
61  * which uses this class to call a static factory method:
62  *
63  * <pre class="code">
64  * &lt;bean id="myObject" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
65  * &lt;property name="staticMethod">&lt;value>com.whatever.MyClassFactory.getInstance&lt;/value>&lt;/property>
66  * &lt;/bean></pre>
67  *
68  * <p>An example of calling a static method then an instance method to get at a
69  * Java system property. Somewhat verbose, but it works.
70  *
71  * <pre class="code">
72  * &lt;bean id="sysProps" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
73  * &lt;property name="targetClass">&lt;value>java.lang.System&lt;/value>&lt;/property>
74  * &lt;property name="targetMethod">&lt;value>getProperties&lt;/value>&lt;/property>
75  * &lt;/bean>
76  *
77  * &lt;bean id="javaVersion" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
78  * &lt;property name="targetObject">&lt;ref local="sysProps"/>&lt;/property>
79  * &lt;property name="targetMethod">&lt;value>getProperty&lt;/value>&lt;/property>
80  * &lt;property name="arguments">
81  * &lt;list>
82  * &lt;value>java.version&lt;/value>
83  * &lt;/list>
84  * &lt;/property>
85  * &lt;/bean></pre>
86  *
87  * @author Colin Sampaleanu
88  * @author Juergen Hoeller
89  * @since 21.11.2003
90  */

91 public class MethodInvokingFactoryBean extends ArgumentConvertingMethodInvoker
92         implements FactoryBean, BeanClassLoaderAware, BeanFactoryAware, InitializingBean {
93
94     private boolean singleton = true;
95
96     private ClassLoader JavaDoc beanClassLoader = ClassUtils.getDefaultClassLoader();
97
98     private ConfigurableBeanFactory beanFactory;
99
100     private boolean initialized = false;
101
102     /** Method call result in the singleton case */
103     private Object JavaDoc singletonObject;
104
105
106     /**
107      * Set if a singleton should be created, or a new object on each
108      * request else. Default is "true".
109      */

110     public void setSingleton(boolean singleton) {
111         this.singleton = singleton;
112     }
113
114     public boolean isSingleton() {
115         return this.singleton;
116     }
117
118     public void setBeanClassLoader(ClassLoader JavaDoc classLoader) {
119         this.beanClassLoader = classLoader;
120     }
121
122     protected Class JavaDoc resolveClassName(String JavaDoc className) throws ClassNotFoundException JavaDoc {
123         return ClassUtils.forName(className, this.beanClassLoader);
124     }
125
126     public void setBeanFactory(BeanFactory beanFactory) {
127         if (beanFactory instanceof ConfigurableBeanFactory) {
128             this.beanFactory = (ConfigurableBeanFactory) beanFactory;
129         }
130     }
131
132     /**
133      * Obtain the TypeConverter from the BeanFactory that this bean runs in,
134      * if possible.
135      * @see ConfigurableBeanFactory#getTypeConverter()
136      */

137     protected TypeConverter getDefaultTypeConverter() {
138         if (this.beanFactory != null) {
139             return this.beanFactory.getTypeConverter();
140         }
141         else {
142             return super.getDefaultTypeConverter();
143         }
144     }
145
146
147     public void afterPropertiesSet() throws Exception JavaDoc {
148         prepare();
149         if (this.singleton) {
150             this.initialized = true;
151             this.singletonObject = doInvoke();
152         }
153     }
154
155     /**
156      * Perform the invocation and convert InvocationTargetException
157      * into the underlying target exception.
158      */

159     private Object JavaDoc doInvoke() throws Exception JavaDoc {
160         try {
161             return invoke();
162         }
163         catch (InvocationTargetException JavaDoc ex) {
164             if (ex.getTargetException() instanceof Exception JavaDoc) {
165                 throw (Exception JavaDoc) ex.getTargetException();
166             }
167             if (ex.getTargetException() instanceof Error JavaDoc) {
168                 throw (Error JavaDoc) ex.getTargetException();
169             }
170             throw ex;
171         }
172     }
173
174
175     /**
176      * Returns the same value each time if the singleton property is set
177      * to "true", otherwise returns the value returned from invoking the
178      * specified method on the fly.
179      */

180     public Object JavaDoc getObject() throws Exception JavaDoc {
181         if (this.singleton) {
182             if (!this.initialized) {
183                 throw new FactoryBeanNotInitializedException();
184             }
185             // Singleton: return shared object.
186
return this.singletonObject;
187         }
188         else {
189             // Prototype: new object on each call.
190
return doInvoke();
191         }
192     }
193
194     /**
195      * Return the type of object that this FactoryBean creates,
196      * or <code>null</code> if not known in advance.
197      */

198     public Class JavaDoc getObjectType() {
199         Method JavaDoc preparedMethod = getPreparedMethod();
200         if (preparedMethod == null) {
201             // Not fully initialized yet -> return null to indicate "not known yet".
202
return null;
203         }
204         return preparedMethod.getReturnType();
205     }
206
207 }
208
Popular Tags