001/* 002 * Copyright 2002-2012 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.beans.factory.config; 018 019import java.io.Serializable; 020 021import org.springframework.beans.BeansException; 022import org.springframework.beans.factory.BeanFactory; 023import org.springframework.beans.factory.ObjectFactory; 024import org.springframework.util.Assert; 025 026/** 027 * A {@link org.springframework.beans.factory.FactoryBean} implementation that 028 * returns a value which is an {@link org.springframework.beans.factory.ObjectFactory} 029 * that in turn returns a bean sourced from a {@link org.springframework.beans.factory.BeanFactory}. 030 * 031 * <p>As such, this may be used to avoid having a client object directly calling 032 * {@link org.springframework.beans.factory.BeanFactory#getBean(String)} to get 033 * a (typically prototype) bean from a 034 * {@link org.springframework.beans.factory.BeanFactory}, which would be a 035 * violation of the inversion of control principle. Instead, with the use 036 * of this class, the client object can be fed an 037 * {@link org.springframework.beans.factory.ObjectFactory} instance as a 038 * property which directly returns only the one target bean (again, which is 039 * typically a prototype bean). 040 * 041 * <p>A sample config in an XML-based 042 * {@link org.springframework.beans.factory.BeanFactory} might look as follows: 043 * 044 * <pre class="code"><beans> 045 * 046 * <!-- Prototype bean since we have state --> 047 * <bean id="myService" class="a.b.c.MyService" scope="prototype"/> 048 * 049 * <bean id="myServiceFactory" 050 * class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean"> 051 * <property name="targetBeanName"><idref local="myService"/></property> 052 * </bean> 053 * 054 * <bean id="clientBean" class="a.b.c.MyClientBean"> 055 * <property name="myServiceFactory" ref="myServiceFactory"/> 056 * </bean> 057 * 058 *</beans></pre> 059 * 060 * <p>The attendant {@code MyClientBean} class implementation might look 061 * something like this: 062 * 063 * <pre class="code">package a.b.c; 064 * 065 * import org.springframework.beans.factory.ObjectFactory; 066 * 067 * public class MyClientBean { 068 * 069 * private ObjectFactory<MyService> myServiceFactory; 070 * 071 * public void setMyServiceFactory(ObjectFactory<MyService> myServiceFactory) { 072 * this.myServiceFactory = myServiceFactory; 073 * } 074 * 075 * public void someBusinessMethod() { 076 * // get a 'fresh', brand new MyService instance 077 * MyService service = this.myServiceFactory.getObject(); 078 * // use the service object to effect the business logic... 079 * } 080 * }</pre> 081 * 082 * <p>An alternate approach to this application of an object creational pattern 083 * would be to use the {@link ServiceLocatorFactoryBean} 084 * to source (prototype) beans. The {@link ServiceLocatorFactoryBean} approach 085 * has the advantage of the fact that one doesn't have to depend on any 086 * Spring-specific interface such as {@link org.springframework.beans.factory.ObjectFactory}, 087 * but has the disadvantage of requiring runtime class generation. Please do 088 * consult the {@link ServiceLocatorFactoryBean ServiceLocatorFactoryBean JavaDoc} 089 * for a fuller discussion of this issue. 090 * 091 * @author Colin Sampaleanu 092 * @author Juergen Hoeller 093 * @since 1.0.2 094 * @see org.springframework.beans.factory.ObjectFactory 095 * @see ServiceLocatorFactoryBean 096 */ 097public class ObjectFactoryCreatingFactoryBean extends AbstractFactoryBean<ObjectFactory<Object>> { 098 099 private String targetBeanName; 100 101 102 /** 103 * Set the name of the target bean. 104 * <p>The target does not <i>have</i> to be a non-singleton bean, but realistically 105 * always will be (because if the target bean were a singleton, then said singleton 106 * bean could simply be injected straight into the dependent object, thus obviating 107 * the need for the extra level of indirection afforded by this factory approach). 108 */ 109 public void setTargetBeanName(String targetBeanName) { 110 this.targetBeanName = targetBeanName; 111 } 112 113 @Override 114 public void afterPropertiesSet() throws Exception { 115 Assert.hasText(this.targetBeanName, "Property 'targetBeanName' is required"); 116 super.afterPropertiesSet(); 117 } 118 119 120 @Override 121 public Class<?> getObjectType() { 122 return ObjectFactory.class; 123 } 124 125 @Override 126 protected ObjectFactory<Object> createInstance() { 127 return new TargetBeanObjectFactory(getBeanFactory(), this.targetBeanName); 128 } 129 130 131 /** 132 * Independent inner class - for serialization purposes. 133 */ 134 @SuppressWarnings("serial") 135 private static class TargetBeanObjectFactory implements ObjectFactory<Object>, Serializable { 136 137 private final BeanFactory beanFactory; 138 139 private final String targetBeanName; 140 141 public TargetBeanObjectFactory(BeanFactory beanFactory, String targetBeanName) { 142 this.beanFactory = beanFactory; 143 this.targetBeanName = targetBeanName; 144 } 145 146 @Override 147 public Object getObject() throws BeansException { 148 return this.beanFactory.getBean(this.targetBeanName); 149 } 150 } 151 152}