spring中实例的创建和初始化过程10
spring中实例的创建和初始化过程10
writeademo 发表于1年前
spring中实例的创建和初始化过程10
  • 发表于 1年前
  • 阅读 82
  • 收藏 0
  • 点赞 0
  • 评论 0

新睿云服务器60天免费使用,快来体验!>>>   

摘要: factoryBean和beanFactory的区别,单例模式下如何获得实例,非单例模式下如何获得,bean创建过程中就将对应的ObjectFactory暴露出来,可以通过getBean使用,进行循环检测

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方法

  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 17
博文 396
码字总数 160385
×
writeademo
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: