欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识

beanName); } else { ret 昆山软件开发 urn doResolveDependency(desc

点击: 次  来源:宝鼎软件 时间:2017-06-01

原文出处: 五月的仓颉

原型Bean加载进程

之前的文章,阐明白非懒加载的单例Bean整个加载进程,除了非懒加载的单例Bean之外,Spring中尚有一种Bean就是原型(Prototype)的Bean,软件开发,看一下界说方法:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="prototypeBean" class="org.xrq.action.PrototypeBean" scope="prototype"  />
    
</beans>

原型Bean加载流程总得来说和单例Bean差不多,看一下差异之处,在AbstractBeanFactory的doGetBean的要领的这一步:

else if (mbd.isPrototype()) {
    // It's a prototype -> create a new instance.
    Object prototypeInstance = null;
    try {
        beforePrototypeCreation(beanName);
        prototypeInstance = createBean(beanName, mbd, args);
    }
    finally {
        afterPrototypeCreation(beanName);
    }
    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

第6行createBean是一样的,原型Bean实例化的主要区别就在于第6行,它是直接建设bean的,而单例bean我们再比拟一下:

if (mbd.isSingleton()) {
    sharedInstance = getSingleton(beanName, new ObjectFactory() {
        public Object getObject() throws BeansException {
            try {
                return createBean(beanName, mbd, args);
            }
            catch (BeansException ex) {
                // Explicitly remove instance from singleton cache: It might have been put there
                // eagerly by the creation process, to allow for circular reference resolution.
                // Also remove any beans that received a temporary reference to the bean.
                destroySingleton(beanName);
                throw ex;
            }
        }
    });
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

它优先会实验getSington,即先实验从singletonObjects中获取一下bean是否存在,假如存在直接返回singletonObjects中的bean工具。

接着,我们看到原型bean建设和单例bean建设的区别还在于第5行和第9行,先看第5行的代码:

protected void beforePrototypeCreation(String beanName) {
    Object curVal = this.prototypesCurrentlyInCreation.get();
    if (curVal == null) {
        this.prototypesCurrentlyInCreation.set(beanName);
    }
    else if (curVal instanceof String) {
        Set<String> beanNameSet = new HashSet<String>(2);
        beanNameSet.add((String) curVal);
        beanNameSet.add(beanName);
        this.prototypesCurrentlyInCreation.set(beanNameSet);
    }
    else {
        Set<String> beanNameSet = (Set<String>) curVal;
        beanNameSet.add(beanName);
    }
}

这段主要是说bean在建设前要把当前beanName配置到ThreadLocal中去,其目标是担保多线程不会同时建设同一个bean。接着看第9行的代码实现,即bean建设之后做了什么:

protected void afterPrototypeCreation(String beanName) {
    Object curVal = this.prototypesCurrentlyInCreation.get();
    if (curVal instanceof String) {
        this.prototypesCurrentlyInCreation.remove();
    }
    else if (curVal instanceof Set) {
        Set<String> beanNameSet = (Set<String>) curVal;
        beanNameSet.remove(beanName);
        if (beanNameSet.isEmpty()) {
            this.prototypesCurrentlyInCreation.remove();
        }
    }
}

很好领略,就是把当前bean移除一下,这样其它线程就可以建设bean了。第11行的代码不看了,意思是假如bean是FactoryBean的实现类的话,挪用getObject()要领获取真正的工具。

byName源码实现

Spring有为开拓者提供Autowire(自动装配)的成果,自动装配最常用的就是byName和byType这两种属性。由于自动装配是为了办理工具注入导致的<property>过多的问题,因此很容易找到byName与byType的Spring源码实现应该在属性注入这一块,定位到属性注入的代码AbstractAutowireCapableBeanFactory的populateBean要领,直接截取重点:

if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
        mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
    MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

    // Add property values based on autowire by name if applicable.
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
        autowireByName(beanName, mbd, bw, newPvs);
    }

    // Add property values based on autowire by type if applicable.
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
        autowireByType(beanName, mbd, bw, newPvs);
    }

    pvs = newPvs;
}