文档章节

spring中实例的创建和初始化过程10

writeademo
 writeademo
发布于 2017/02/13 21:26
字数 1228
阅读 89
收藏 0

FactoryBean的使用

在<bean>配置中需要大量的配置信息,这是采用编码的方式,减少配置。spring提供了一个

org.Springframework.bean.factory.FactoryBean的工厂接口,Spring自身提供了70多个FactoryBean的实现,他们隐藏了实例化一些复杂bean的细节,给上层应用带来了便利。

package org.springframework.beans.factory;

public interface FactoryBean<T> {

         T getObject() throws Exception;

         Class<?> getObjectType();

         boolean isSingleton();

 

}

T getObject():返回FactoryBean创建的bean实例,如果isSingleton返回true,该实例会放到Spring容器中单实例缓冲池中。

boolean isSingleton();由FactoryBean创建的bean实例的作用域是singleton还是prototype

 

Class<T>getObjectType():返回创建的bean类型

public class CarFactoryBean implements FactoryBean<Car> {

         private String carInfo;

 

         @Override

         public Car getObject() throws Exception {

                   Car car = new Car();

                   String[] infos = carInfo.split(",");

                   car.setBrand(infos[0]);

                   car.setMaxSpeed(Integer.valueOf(infos[1]));

                   car.setPrice(Double.valueOf(infos[2]));

                   return car;

         }

 

         @Override

         public Class<?> getObjectType() {

 

                   return Car.class;

         }

 

         @Override

         public boolean isSingleton() {

                   // TODO Auto-generated method stub

                   return false;

         }

 

         public String getCarInfo() {

                   return carInfo;

         }

 

         public void setCarInfo(String carInfo) {

                   this.carInfo = carInfo;

         }

 

}

通过接口FactoryBean实现,减少bean中属性配置

 

 

缓存中获取单例bean

 

单例在spring的同一个容器中只会被创建一次,后续再获取bean直接从单例缓存中获取

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry{}

@Override

    public Object getSingleton(String beanName) {

        return getSingleton(beanName, true);

    }

 

    /**

     * Return the (raw) singleton object registered under the given name.

     * <p>Checks already instantiated singletons and also allows for an early

     * reference to a currently created singleton (resolving a circular reference).

     * @param beanName the name of the bean to look for

     * @param allowEarlyReference whether early references should be created or not

     * @return the registered singleton object, or {@code null} if none found

     */

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {

        Object singletonObject = this.singletonObjects.get(beanName);

        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {

            synchronized (this.singletonObjects) {

                singletonObject = this.earlySingletonObjects.get(beanName);

                if (singletonObject == null && allowEarlyReference) {

                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);

                    if (singletonFactory != null) {

                        singletonObject = singletonFactory.getObject();

                        this.earlySingletonObjects.put(beanName, singletonObject);

                        this.singletonFactories.remove(beanName);

                    }

                }

            }

        }

        return (singletonObject != NULL_OBJECT ? singletonObject : null);

    }

首先尝试从singletonObjects里面获取实例,如果获取不到再从earlySingletonObjects里面获得,如果获取不到,再尝试从singletonFactories里面获取beanName对应的ObjectFactory,然后调用objectFactories里面的getObject来创建bean,并放到earlySingletonObjects里面去。

这里涉及存储bean的不同的map:

singletonObjects:用于保存beanName和创建bean实例之间的关系

earlySingletonObjects:也是保存beanname和创建bean实例之间的关系,不同之处在于,在bean创建过程中,就可以通过getBean获取到,是为了用来检测循环引用

registeredSingleton用来保存当前所有已经注册的bean;

 

 

 

spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提前曝光加入到缓存中

 

 

 

 

从bean的实例中获取对象

首先要检查bean的正确性,是否是factoryBean类型的bean,如果是,调用该bean对应的factoryBean实例中的getObject()作为返回值

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory{}

 

protected Object getObjectForBeanInstance(

            Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {

 

        // Don't let calling code try to dereference the factory if the bean isn't a factory.

        if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {

            throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());

        }

 

        // 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());

            object = getObjectFromFactoryBean(factory, beanName, !synthetic);

        }

        return object;

    }

1factoryBean正确性进行验证

2对非FactoryBean不做任何处理

3bean进行转化

4Factory中获得bean的工作委托给getObjectFromFactoryBean

public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry {}

    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)

                    Object alreadyThere = this.factoryBeanObjectCache.get(beanName);

                    if (alreadyThere != null) {

                        object = alreadyThere;

                    }

                    else {

                        if (object != null && shouldPostProcess) {

                            try {

                                object = postProcessObjectFromFactoryBean(object, beanName);

                            }

                            catch (Throwable ex) {

                                throw new BeanCreationException(beanName,

                                        "Post-processing of FactoryBean's singleton object failed", ex);

                            }

                        }

                        this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));

                    }

                }

                return (object != NULL_OBJECT ? object : null);

            }

        }

        else {

            Object object = doGetObjectFromFactoryBean(factory, beanName);

            if (object != null && shouldPostProcess) {

                try {

                    object = postProcessObjectFromFactoryBean(object, beanName);

                }

                catch (Throwable ex) {

                   throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);

                }

            }

            return object;

        }

    }

单例时直接从FactoryBeanObjectCache中获取;

 

 

private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)

            throws BeanCreationException {

 

        Object object;

        try {

            if (System.getSecurityManager() != null) {

                AccessControlContext acc = getAccessControlContext();

                try {

                    object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {

                        @Override

                        public Object run() throws Exception {

                                return factory.getObject();

                            }

                        }, acc);

                }

                catch (PrivilegedActionException pae) {

                    throw pae.getException();

                }

            }

            else {

                object = factory.getObject();

            }

        }

        catch (FactoryBeanNotInitializedException ex) {

            throw new BeanCurrentlyInCreationException(beanName, ex.toString());

        }

        catch (Throwable ex) {

            throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);

        }

 

        // Do not accept a null value for a FactoryBean that's not fully

        // initialized yet: Many FactoryBeans just return null then.

        if (object == null && isSingletonCurrentlyInCreation(beanName)) {

            throw new BeanCurrentlyInCreationException(

                    beanName, "FactoryBean which is currently in creation returned null from getObject");

        }

        return object;

    }

 

得到Object后又做了一些处理

PostProcessorsAfterInitialization

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory

        implements AutowireCapableBeanFactory{}

 

    @Override

    protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {

        return applyBeanPostProcessorsAfterInitialization(object, beanName);

    }

@Override

    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)

            throws BeansException {

 

        Object result = existingBean;

        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {

            result = beanProcessor.postProcessAfterInitialization(result, beanName);

            if (result == null) {

                return result;

            }

        }

        return result;

    }

尽可能保证所有bean的初始化后都会调用注册的BeanPostProcessorpostProcessAfterInitialization方法

© 著作权归作者所有

共有 人打赏支持
writeademo
粉丝 24
博文 533
码字总数 191186
作品 0
东城
Spring Ioc 源码分析(二)- bean的实例化

在 Spring Ioc 源码分析(一)- XML 解析 中,我们完成了从 xml 到 BeanDefinition的过程。只是把 xml描述的 Bean定义转换为 Java对象描述。本文将讲解 spring 如何利用 BeanDefinition 完成...

我叫董先森
2017/10/19
0
0
【死磕 Spring】—– IOC 之开启 bean 的加载

原文出自:http://cmsblogs.com (此图来自《Spring 揭秘》) Spring IOC 容器所起的作用如上图所示,它会以某种方式加载 Configuration Metadata,将其解析注册到容器内部,然后回根据这些信息...

chenssy
今天
0
0
Spring Bean的生命周期,《Spring 实战》书中的官方说法

连着两天的面试 ,都问到了 Spring 的Bean的生命周期,其中还包括 昨晚一波阿里的电话面试。这里找到了Spring 实战中的官方说法。希望各位要面试的小伙伴记住,以后有可能,或者是有时间 去看...

致未来的自己
08/02
0
0
【Spring】详解Spring中Bean的加载

之前写过bean的解析,这篇来讲讲bean的加载,加载要比bean的解析复杂些, 该文之前在小编原文中有发表过,要看原文的可以直接点击原文查看, 从之前的例子开始,Spring中加载一个bean的方式:...

weknow
2017/04/06
0
1
Spring IOC 实现原理

Spring IOC 实现原理 IOC: Inversion of Control ,即 "控制反转" , 不是什么技术,而是一种思想。原先需要自行实例化的对象, 交给IOC容器去实现。那么控制反转,谁被控制? 谁被反转 ? 在...

起个名忒难
05/17
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Python深体验,常见的数据处理方式(必须要懂的)

1.缺失值处理 - 拉格朗日插值法 input_file数据文件内容(存在部分缺失值): from scipy.interpolate import lagrangeimport pandas as pdimport numpy as npinput_file = './dat...

无也Python
27分钟前
2
0
Spring MVC注解故障追踪记

Spring MVC是美团点评很多团队使用的Web框架。在基于Spring MVC的项目里,注解的使用几乎遍布在项目中的各个模块,有Java提供的注解,如:@Override、@Deprecated等;也有Spring提供的注解,...

Skqing
28分钟前
4
0
区块链入门教程以太坊源码分析cmd包分析

  兄弟连区块链入门教程以太坊源码分析cmd包分析。 ### cmd包概述 * geth 主要Ethereum CLI客户端。它是Ethereum网络(eth主网,测试网络或私有网)的入口点,使用此命令可以使节点作为ful...

兄弟连区块链入门教程
30分钟前
1
0
@Autowired 报红线

代码可正常跑,不过红线看着有点难受,解决方案 使用@Autowired(required=false) 或者@Resource. 这两者区别网上一大堆

斩神魂
36分钟前
3
0
DataTable中检索信息 (C#)

C#_从DataTable中检索信息 存在于内存中的虚拟表DataTable,绑定在数据显示控件后,如果想在再检索其中某些信息,可以利用DataTable.Select方法进行检索,避免了重复的读取数据库。Select方法...

CS-CS01
43分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部