原型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; }