spring源码分析系列 (8) FactoryBean工厂类机制
FactoryBean对象设计是为了生成简化对象, 在BeanDefinition加载的时候FactoryBean的beanName会带有特殊前缀&.
public interface FactoryBean<T> { @Nullable T getObject() throws Exception; @Nullable Class<?> getObjectType(); default boolean isSingleton() { return true; } }
在BeanFactory中的定义:
public interface BeanFactory { // FactoryBean前缀, 用于区分FactoryBean产生的bean. 如果myJndiObject为FactoryBean, 可以用&myJndiObject获取工厂类 /** * Used to dereference a {@link FactoryBean} instance and distinguish it from * beans <i>created</i> by the FactoryBean. For example, if the bean named * {@code myJndiObject} is a FactoryBean, getting {@code &myJndiObject} * will return the factory, not the instance returned by the factory. */ String FACTORY_BEAN_PREFIX = "&";
// ......... }
实际应用中如ProxyFactoryBean可以将代理的具体细节隐藏起来, 只需要通过getObject获取代理. 还有CronTriggerFactoryBean配置使用quartz时候简化配置等. 以下为一个示例demo:
DecorationFactoryBean.java
/** * bean 装饰工厂 * @author */ public class DecorationFactoryBean implements FactoryBean<Bean> { @Override public Bean getObject() throws Exception { Bean bean = new Bean() ; bean.setName("在FactoryBean统一处理属性") ; return bean; } @Override public Class<?> getObjectType() { return Bean.class; } }
ioc-FactoryBean.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" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="bean" class="com.nancy.ioc.FactoryBean.DecorationFactoryBean/"> </beans>
FactoryBeanTest.java
public class FactoryBeanTest { private ApplicationContext applicationContext ; @Before public void beforeApplicationContext(){ /** * ApplicationContext 自动注册 BeanPostProcessor、InstantiationAwareBeanPostProcessor、BeanFactoryPostProcessor * 不需要手动注册 * */ applicationContext = new ClassPathXmlApplicationContext("ioc-FactoryBean.xml") ; } @Test public void test(){ Bean bean = (Bean) applicationContext.getBean("bean"); System.out.println(bean); DecorationFactoryBean factoryBean = (DecorationFactoryBean) applicationContext.getBean("&bean"); System.out.println(factoryBean); } @After public void after(){ if(applicationContext != null){ ((ClassPathXmlApplicationContext)applicationContext).close(); } } }
运行结果, 虽然声明的的是工厂类DecorationFactoryBean, 实际正确返回Bean的实例.
17:11:08.692 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@797badd3
17:11:09.150 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 1 bean definitions from class path resource [ioc-FactoryBean.xml]
17:11:10.974 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean'
Bean{name='在FactoryBean统一处理属性'}
com.nancy.ioc.FactoryBean.DecorationFactoryBean@73eb439a
17:11:39.008 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Closing org.springframework.context.support.ClassPathXmlApplicationContext@797badd3, started on Fri Apr 26 17:11:08 CST 2019
由bean创建过程分析FactoryBean获取bean的流程: 入口 AbstractAutowireCapableBeanFactory.getObjectForBeanInstance
AbstractAutowireCapableBeanFactory.getObjectForBeanInstance
// 重载父类AbstractBeanFactory方法, FactoryBean获取入口 @Override protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { String currentlyCreatedBean = this.currentlyCreatedBean.get(); if (currentlyCreatedBean != null) { registerDependentBean(beanName, currentlyCreatedBean); } return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd); }
AbstractBeanFactory.getObjectForBeanInstance
/** * Get the object for the given bean instance, either the bean * instance itself or its created object in case of a FactoryBean. * @param beanInstance the shared bean instance * @param name name that may include factory dereference prefix * @param beanName the canonical bean name * @param mbd the merged bean definition * @return the object to expose for the bean */ protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { // 判断是否为工厂Bean 合法性校验 // Don't let calling code try to dereference the factory if the bean isn't a factory. if (BeanFactoryUtils.isFactoryDereference(name)) { if (beanInstance instanceof NullBean) { return beanInstance; } if (!(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass()); } } // 可以获取工厂Bean本身 // Now we have the bean instance, which may be a normal bean or a FactoryBean. // If it's a FactoryBean, we use it to create a bean instance, unless the // caller actually wants a reference to the factory. if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } // 查询缓存是否存 Object object = null; if (mbd == null) { object = getCachedObjectForFactoryBean(beanName); } if (object == null) { // Return bean instance from factory. FactoryBean<?> factory = (FactoryBean<?>) beanInstance; // Caches object obtained from FactoryBean if it is a singleton. if (mbd == null && containsBeanDefinition(beanName)) { mbd = getMergedLocalBeanDefinition(beanName); } boolean synthetic = (mbd != null && mbd.isSynthetic()); // 使用工厂方法获取bean object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }
FactoryBeanRegistrySupport
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) { // 单例对象获取bean if (factory.isSingleton() && containsSingleton(beanName)) { synchronized (getSingletonMutex()) { Object object = this.factoryBeanObjectCache.get(beanName); if (object == null) { // 实际调用工厂方法获取bean地方 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) Object alreadyThere = this.factoryBeanObjectCache.get(beanName); if (alreadyThere != null) { object = alreadyThere; } else { // 涉及到bean声明周期BeanPostProcess, 实例话后需要触发 if (shouldPostProcess) { if (isSingletonCurrentlyInCreation(beanName)) { // Temporarily return non-post-processed object, not storing it yet.. return object; } beforeSingletonCreation(beanName); try { object = postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", 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; } }
实际调用工厂方法获取bean地方
1 private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName) 2 throws BeanCreationException { 3 Object object; 4 try { 5 if (System.getSecurityManager() != null) { 6 AccessControlContext acc = getAccessControlContext(); 7 try { 8 object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc); 9 } 10 catch (PrivilegedActionException pae) { 11 throw pae.getException(); 12 } 13 } 14 else { 15 object = factory.getObject(); 16 } 17 } 18 catch (FactoryBeanNotInitializedException ex) { 19 throw new BeanCurrentlyInCreationException(beanName, ex.toString()); 20 } 21 catch (Throwable ex) { 22 throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex); 23 } 24 25 // Do not accept a null value for a FactoryBean that's not fully 26 // initialized yet: Many FactoryBeans just return null then. 27 if (object == null) { 28 if (isSingletonCurrentlyInCreation(beanName)) { 29 throw new BeanCurrentlyInCreationException( 30 beanName, "FactoryBean which is currently in creation returned null from getObject"); 31 } 32 object = new NullBean(); 33 } 34 return object; 35 } 36 37 @Override 38 protected Object postProcessObjectFromFactoryBean(Object object, String beanName) { 39 return applyBeanPostProcessorsAfterInitialization(object, beanName); 40 } 41 @Override 42 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) 43 throws BeansException { 44 45 Object result = existingBean; 46 for (BeanPostProcessor processor : getBeanPostProcessors()) { 47 Object current = processor.postProcessAfterInitialization(result, beanName); 48 if (current == null) { 49 return result; 50 } 51 result = current; 52 }
由此串联起来FactoryBean运行机制实质简化复杂的bean生产以及隐藏一些实现的过程. 在众多框架中利用拓展FactoryBean, 减少使用框架使用难度.