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