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; }
天天用心记录一点点。内容也许不重要,但习惯很重要!