spring中FactoryBean工廠模式使用
阿新 • • 發佈:2019-01-07
一、簡介
FactoryBean是spring中工廠模式的實現,可以通過配置建立不同的物件。
通常可用在基於不同配置產生不同物件場景中,如資料庫連線(線上、測試環境連線引數不一樣)。
二、FactoryBean<T>原始碼
package org.springframework.beans.factory; import org.springframework.lang.Nullable; /** * Interface to be implemented by objects used within a {@link BeanFactory} which * are themselves factories for individual objects. If a bean implements this * interface, it is used as a factory for an object to expose, not directly as a * bean instance that will be exposed itself. * * <p><b>NB: A bean that implements this interface cannot be used as a normal bean.</b> * A FactoryBean is defined in a bean style, but the object exposed for bean * references ({@link #getObject()}) is always the object that it creates. * * <p>FactoryBeans can support singletons and prototypes, and can either create * objects lazily on demand or eagerly on startup. The {@link SmartFactoryBean} * interface allows for exposing more fine-grained behavioral metadata. * * <p>This interface is heavily used within the framework itself, for example for * the AOP {@link org.springframework.aop.framework.ProxyFactoryBean} or the * {@link org.springframework.jndi.JndiObjectFactoryBean}. It can be used for * custom components as well; however, this is only common for infrastructure code. * * <p><b>{@code FactoryBean} is a programmatic contract. Implementations are not * supposed to rely on annotation-driven injection or other reflective facilities.</b> * {@link #getObjectType()} {@link #getObject()} invocations may arrive early in * the bootstrap process, even ahead of any post-processor setup. If you need access * other beans, implement {@link BeanFactoryAware} and obtain them programmatically. * * <p>Finally, FactoryBean objects participate in the containing BeanFactory's * synchronization of bean creation. There is usually no need for internal * synchronization other than for purposes of lazy initialization within the * FactoryBean itself (or the like). * * @author Rod Johnson * @author Juergen Hoeller * @since 08.03.2003 * @see org.springframework.beans.factory.BeanFactory * @see org.springframework.aop.framework.ProxyFactoryBean * @see org.springframework.jndi.JndiObjectFactoryBean */ public interface FactoryBean<T> { /** * Return an instance (possibly shared or independent) of the object * managed by this factory. * <p>As with a {@link BeanFactory}, this allows support for both the * Singleton and Prototype design pattern. * <p>If this FactoryBean is not fully initialized yet at the time of * the call (for example because it is involved in a circular reference), * throw a corresponding {@link FactoryBeanNotInitializedException}. * <p>As of Spring 2.0, FactoryBeans are allowed to return {@code null} * objects. The factory will consider this as normal value to be used; it * will not throw a FactoryBeanNotInitializedException in this case anymore. * FactoryBean implementations are encouraged to throw * FactoryBeanNotInitializedException themselves now, as appropriate. * @return an instance of the bean (can be {@code null}) * @throws Exception in case of creation errors * @see FactoryBeanNotInitializedException */ @Nullable T getObject() throws Exception; /** * Return the type of object that this FactoryBean creates, * or {@code null} if not known in advance. * <p>This allows one to check for specific types of beans without * instantiating objects, for example on autowiring. * <p>In the case of implementations that are creating a singleton object, * this method should try to avoid singleton creation as far as possible; * it should rather estimate the type in advance. * For prototypes, returning a meaningful type here is advisable too. * <p>This method can be called <i>before</i> this FactoryBean has * been fully initialized. It must not rely on state created during * initialization; of course, it can still use such state if available. * <p><b>NOTE:</b> Autowiring will simply ignore FactoryBeans that return * {@code null} here. Therefore it is highly recommended to implement * this method properly, using the current state of the FactoryBean. * @return the type of object that this FactoryBean creates, * or {@code null} if not known at the time of the call * @see ListableBeanFactory#getBeansOfType */ @Nullable Class<?> getObjectType(); /** * Is the object managed by this factory a singleton? That is, * will {@link #getObject()} always return the same object * (a reference that can be cached)? * <p><b>NOTE:</b> If a FactoryBean indicates to hold a singleton object, * the object returned from {@code getObject()} might get cached * by the owning BeanFactory. Hence, do not return {@code true} * unless the FactoryBean always exposes the same reference. * <p>The singleton status of the FactoryBean itself will generally * be provided by the owning BeanFactory; usually, it has to be * defined as singleton there. * <p><b>NOTE:</b> This method returning {@code false} does not * necessarily indicate that returned objects are independent instances. * An implementation of the extended {@link SmartFactoryBean} interface * may explicitly indicate independent instances through its * {@link SmartFactoryBean#isPrototype()} method. Plain {@link FactoryBean} * implementations which do not implement this extended interface are * simply assumed to always return independent instances if the * {@code isSingleton()} implementation returns {@code false}. * <p>The default implementation returns {@code true}, since a * {@code FactoryBean} typically manages a singleton instance. * @return whether the exposed object is a singleton * @see #getObject() * @see SmartFactoryBean#isPrototype() */ default boolean isSingleton() { return true; } }
閱讀原碼,FactoryBean是通過泛型傳遞實際物件的型別,它有三個方法:
a)getObject(),返回生成的物件;
b)getObjectType(),返回物件型別;
c)isSingleton() ,是否是單例,true:是,false:不是。
三、使用示例
1、定義物件類 Stu.class
public class Stu { private String stuNo; private String stuName; public Stu() { } public Stu(String stuNo, String stuName) { this.stuNo = stuNo; this.stuName = stuName; } public String getStuNo() { return stuNo; } public void setStuNo(String stuNo) { this.stuNo = stuNo; } public String getStuName() { return stuName; } public void setStuName(String stuName) { this.stuName = stuName; } }
2、定義對應的FactoryBean類 StuFactoryBean.class
public class StuFactoryBean implements FactoryBean<Stu> { private String info; public StuFactoryBean() { } @Override public Stu getObject() throws Exception { return new Stu(info.split("_")[0], info.split("_")[1]); } @Override public Class<?> getObjectType() { return Stu.class; } /** * 是否是單例 * * @return true:是 false:否 */ @Override public boolean isSingleton() { return true; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } }
3、spring配置檔案spring-bean.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="stuOne" class="com.dragon.study.spring.StuFactoryBean"> <property name="info" value="001_apple" /> </bean> <bean id="stuTwo" class="com.dragon.study.spring.StuFactoryBean" > <property name="info" value="002_orange" /> </bean> </beans>
4、測試
public class FactoryBeanStudy { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:spring-bean.xml"); Stu s1 = ctx.getBean("stuOne", Stu.class); Stu s2 = ctx.getBean("stuOne", Stu.class); System.out.println(s1 == s2); Stu s3 = ctx.getBean("stuTwo", Stu.class); System.out.println(s1 == s3); } }
輸出結果:
true
false