• 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, 减少使用框架使用难度. 

  • 相关阅读:
    Show, Attend and Tell: Neural Image Caption Generation with Visual Attention
    (转)Awesome GAN for Medical Imaging
    (转)Awesome Object Detection
    (转)Awesome PyTorch List
    深度学习课程笔记(十七)Meta-learning (Model Agnostic Meta Learning)
    深度学习课程笔记(十六)Recursive Neural Network
    (转)Multi-Object-Tracking-Paper-List
    深度学习课程笔记(十五)Recurrent Neural Network
    (转)Awsome Domain-Adaptation
    论文阅读:Learning Visual Question Answering by Bootstrapping Hard Attention
  • 原文地址:https://www.cnblogs.com/xiaoxing/p/10774669.html
Copyright © 2020-2023  润新知