Spring 系列目錄(http://www.javashuo.com/article/p-kqecupyl-bm.html)html
通常狀況下,Spring 經過反射機制利用 bean 的 class 屬性指定實現類來實例化 bean。在某些狀況下特別是整合第三方包時,實例化 bean 過程比較複雜,若是按照傳統的方式,則須要在 XML 中提供大量的配置信息,配置方式的靈活性是受限的,這時採用編碼的方式可能會獲得一個簡單的方案。Spring 爲此提供了一個 FactoryBean 的工廠類接口,用戶能夠經過實現該接口定製實例化 bean 的邏輯。java
public interface FactoryBean<T> { T getObject() throws Exception; Class<?> getObjectType(); default boolean isSingleton() { return true; } }
在該接口中還定義瞭如下3個方法:spring
(1) T getObject():返回由 FactoryBean 建立的 bean 實例,若是 isSingleton() 返回 true,則該實例會放到 Spring 容器中單實例存池中緩存
(2) boolean isSingleton():返回由 FactoryBean 建立的 bean 實例的做用域是 singleton 仍是 prototypeide
(3) Class<?> getObjectType():返回 FactoryBean 建立的 bean 類型。post
在以下的 Bean 經過 FactoryBean 注入this
public class CarFactoryBean implements FactoryBean<Car> { private String carInfo; @Override public Car getObject() throws Exception { String[]infos = carInfo.split(","); return Car car=new Car(infos[0], Integer.parseInt(infos[1]), Double.parseDouble(infos[2])); } @Override public Class<?> getObjectType() { return null; } } public class Car { private String brand; private int maxSpeed; private Double price; // get/set }
有了這個 CarFactoryBean 後,就能夠在配置文件中使用下面這種自定義的配置方式配置了編碼
<bean id="car" class="spring.factory_bean.CarFactoryBean"> <property name="carInfo" value="紅旗CA72,200,20000.00"/> </bean>
當調用 getBean("car") 時,Spring 經過反射機制發現 CarFactoryBean 實現了 FactoryBean 的接口,這時 Spring 容器就調用接口方法 CarFactoryBean#getObject() 方法返回。若是但願獲取 CarFactoryBean 的實例,則須要在使用 getBean(beanName) 方法時在 beanName 前顯示的加上 & 前綴,例如 getBean("&car")prototype
FactoryBeanRegistrySupport 提供了對 FactoryBean 的支持,最重要的方法是 getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess)
,這個方法經過 factoryBean 獲取 bean 對象。code
(1) 屬性
// 緩存 beanName -> FactoryBean 的集合 private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);
(2) getObjectFromFactoryBean 註冊
getObjectFromFactoryBean 負責從 FactoryBean#getObject() 中獲取真正想要的 bean 對象,而不是 FactoryBean 自己。AbstractBeanFactory#getObjectForBeanInstance 獲取 bean 以前會判斷是否是 FactoryBean。
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) { if (factory.isSingleton() && containsSingleton(beanName)) { synchronized (getSingletonMutex()) { Object object = this.factoryBeanObjectCache.get(beanName); if (object == null) { object = doGetObjectFromFactoryBean(factory, beanName); // Only post-process and store if not put there already during getObject() call above // (e.g. because of circular reference processing triggered by custom getBean calls) // TODO ? 什麼意思,循環引用? Object alreadyThere = this.factoryBeanObjectCache.get(beanName); if (alreadyThere != null) { object = alreadyThere; } else { if (shouldPostProcess) { if (isSingletonCurrentlyInCreation(beanName)) { // Temporarily return non-post-processed object, not storing it yet.. return object; } beforeSingletonCreation(beanName); try { // 外面 BeanPostProcessor 做用在 factory 上,沒有做用在實際想要的實例上,這邊補一個 // 也就是說 BeanPostProcessor 的 postProcessBeforeInitialization 不會做用在 FactoryBean 上 object = postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable ex) { throw new BeanCreationException(beanName", ex); } finally { afterSingletonCreation(beanName); } } if (containsSingleton(beanName)) { this.factoryBeanObjectCache.put(beanName, object); } } } return object; } } else { Object object = doGetObjectFromFactoryBean(factory, beanName); if (shouldPostProcess) { try { object = postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex); } } return object; } } // 調用 FactoryBean#getObject() 建立 bean private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName) throws BeanCreationException { Object object = factory.getObject(); if (object == null) { if (isSingletonCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException( beanName, "FactoryBean which is currently in creation returned null from getObject"); } object = new NullBean(); } return object; } // 子類重寫 protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException { return object; }
(3) 查找與刪除
protected Object getCachedObjectForFactoryBean(String beanName) { return this.factoryBeanObjectCache.get(beanName); } @Override protected void removeSingleton(String beanName) { synchronized (getSingletonMutex()) { super.removeSingleton(beanName); this.factoryBeanObjectCache.remove(beanName); } } @Override protected void clearSingletonCache() { synchronized (getSingletonMutex()) { super.clearSingletonCache(); this.factoryBeanObjectCache.clear(); } }
(4) 其它方法
protected Class<?> getTypeForFactoryBean(final FactoryBean<?> factoryBean) { return factoryBean.getObjectType(); } protected FactoryBean<?> getFactoryBean(String beanName, Object beanInstance) throws BeansException { if (!(beanInstance instanceof FactoryBean)) { throw new BeanCreationException(beanName, "Bean instance of type [" + beanInstance.getClass() + "] is not a FactoryBean"); } return (FactoryBean<?>) beanInstance; }
天天用心記錄一點點。內容也許不重要,但習慣很重要!