spring源码分析系列 (8) FactoryBean工厂类机制

更多文章点击--spring源码分析系列

 

1、FactoryBean设计目的以及使用

2、FactoryBean工厂类机制运行机制分析

 

1、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>
ioc-FactoryBean.xml

 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();
        }
    }
}
FactoryBeanTest.java

 运行结果, 虽然声明的的是工厂类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

  

2、FactoryBean工厂类机制运行机制分析

由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         }
doGetObjectFromFactoryBean

 

由此串联起来FactoryBean运行机制实质简化复杂的bean生产以及隐藏一些实现的过程.  在众多框架中利用拓展FactoryBean, 减少使用框架使用难度. 

 

posted on 2019-04-26 17:52  小猩  阅读(659)  评论(0编辑  收藏  举报

导航