文档章节

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

writeademo
 writeademo
发布于 2017/02/13 21:26
字数 1228
阅读 92
收藏 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
粉丝 25
博文 578
码字总数 214562
作品 0
东城
私信 提问
Spring Ioc 源码分析(二)- bean的实例化

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

我叫董先森
2017/10/19
0
0
【死磕 Spring】—– IOC 之分析各 scope 的 bean 创建

原文出自:http://cmsblogs.com 在 Spring 中存在着不同的 scope,默认是 singleton ,还有 prototype、request 等等其他的 scope,他们的初始化步骤是怎样的呢?这个答案在这篇博客中给出。...

chenssy
2018/10/24
0
0
【死磕 Spring】—– IOC 之构造函数实例化 bean

原文出自:http://cmsblogs.com 用于实例化 bean,它会根据不同情况选择不同的实例化策略来完成 bean 的初始化,主要包括: Supplier 回调: 工厂方法初始化: 构造函数自动注入初始化: 默认...

chenssy
2018/10/25
0
0
【死磕 Spring】—– IOC 之开启 bean 的加载

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

chenssy
2018/10/18
0
0
【Spring】详解Spring中Bean的加载

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

weknow
2017/04/06
0
1

没有更多内容

加载失败,请刷新页面

加载更多

开始看《Java学习笔记》

虽然书买了很久,但一直没看。这其中也写过一些Java程序,但都是基于IDE的帮助和对C#的理解来写的,感觉不踏实。 林信良的书写得蛮好的,能够帮助打好基础,看得出作者是比较用心的。 第1章概...

max佩恩
昨天
6
0
Redux 三大原则

1.单一数据源 在传统的MVC架构中,我们可以根据需要创建无数个Model,而Model之间可以互相监听、触发事件甚至循环或嵌套触发事件,这些在Redux中都是不被允许的。 因为在Redux的思想里,一个...

wenxingjun
昨天
3
0
跟我学Spring Cloud(Finchley版)-12-微服务容错三板斧

至此,我们已实现服务发现、负载均衡,同时,使用Feign也实现了良好的远程调用——我们的代码是可读、可维护的。理论上,我们现在已经能构建一个不错的分布式应用了,但微服务之间是通过网络...

周立_ITMuch
昨天
2
0
XML

学习目标  能够说出XML的作用  能够编写XML文档声明  能够编写符合语法的XML  能够通过DTD约束编写XML文档  能够通过Schema约束编写XML文档  能够通过Dom4j解析XML文档 第1章 xm...

stars永恒
昨天
0
0
RabbitMQ学习(2)

1. 生产者客户端 void basicPublish(String exchange, String routingKey, boolean mandatory, boolean immediate, BasicProperties props, byte[] body) 1. 在生产者客户端发送消息时,首先......

江左煤郎
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部