原型Bean加載過程
之前的文章,分析了非懶加載的單例Bean整個加載過程,除了非懶加載的單例Bean之外,Spring中還有一種Bean就是原型(Prototype)的Bean,看一下定義方式:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 6 7 <bean id="prototypeBean" class="org.xrq.action.PrototypeBean" scope="prototype" /> 8 9 </beans>
原型Bean加載流程總得來說和單例Bean差不多,看一下不同之處,在AbstractBeanFactory的doGetBean的方法的這一步:
1 else if (mbd.isPrototype()) {
2 // It's a prototype -> create a new instance.
3 Object prototypeInstance = null;
4 try {
5 beforePrototypeCreation(beanName);
6 prototypeInstance = createBean(beanName, mbd, args);
7 }
8 finally {
9 afterPrototypeCreation(beanName);
10 }
11 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
12 }
第6行createBean是一樣的,原型Bean實例化的主要區別就在於第6行,它是直接創建bean的,而單例bean我們再對比一下:
1 if (mbd.isSingleton()) {
2 sharedInstance = getSingleton(beanName, new ObjectFactory() {
3 public Object getObject() throws BeansException {
4 try {
5 return createBean(beanName, mbd, args);
6 }
7 catch (BeansException ex) {
8 // Explicitly remove instance from singleton cache: It might have been put there
9 // eagerly by the creation process, to allow for circular reference resolution.
10 // Also remove any beans that received a temporary reference to the bean.
11 destroySingleton(beanName);
12 throw ex;
13 }
14 }
15 });
16 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
17 }
它優先會嘗試getSington,即先嘗試從singletonObjects中獲取一下bean是否存在,如果存在直接返回singletonObjects中的bean對象。
接著,我們看到原型bean創建和單例bean創建的區別還在於第5行和第9行,先看第5行的代碼:
1 protected void beforePrototypeCreation(String beanName) {
2 Object curVal = this.prototypesCurrentlyInCreation.get();
3 if (curVal == null) {
4 this.prototypesCurrentlyInCreation.set(beanName);
5 }
6 else if (curVal instanceof String) {
7 Set<String> beanNameSet = new HashSet<String>(2);
8 beanNameSet.add((String) curVal);
9 beanNameSet.add(beanName);
10 this.prototypesCurrentlyInCreation.set(beanNameSet);
11 }
12 else {
13 Set<String> beanNameSet = (Set<String>) curVal;
14 beanNameSet.add(beanName);
15 }
16 }
這段主要是說bean在創建前要把當前beanName設置到ThreadLocal中去,其目的是保證多線程不會同時創建同一個bean。接著看第9行的代碼實現,即bean創建之後做了什麼:
1 protected void afterPrototypeCreation(String beanName) {
2 Object curVal = this.prototypesCurrentlyInCreation.get();
3 if (curVal instanceof String) {
4 this.prototypesCurrentlyInCreation.remove();
5 }
6 else if (curVal instanceof Set) {
7 Set<String> beanNameSet = (Set<String>) curVal;
8 beanNameSet.remove(beanName);
9 if (beanNameSet.isEmpty()) {
10 this.prototypesCurrentlyInCreation.remove();
11 }
12 }
13 }
很好理解,就是把當前bean移除一下,這樣其它線程就可以創建bean了。第11行的代碼不看了,意思是如果bean是FactoryBean的實現類的話,調用getObject()方法獲取真正的對象。
byName源碼實現
Spring有為開發者提供Autowire(自動裝配)的功能,自動裝配最常用的就是byName和byType這兩種屬性。由於自動裝配是為了解決對象注入導致的<property>過多的問題,因此很容易找到byName與byType的Spring源碼實現應該在屬性注入這一塊,定位到屬性注入的代碼AbstractAutowireCapableBeanFactory的populateBean方法,直接截取重點:
1 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
2 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
3 MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
4
5 // Add property values based on autowire by name if applicable.
6 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
7 autowireByName(beanName, mbd, bw, newPvs);
8 }
9
10 // Add property values based on autowire by type if applicable.
11 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
12 autowireByType(beanName, mbd, bw, newPvs);
13 }
14
15 pvs = newPvs;
16 }
看到第6行~第8行判斷是否byName形式,是就執行byName自動裝配代碼;第11行~第13行判斷是否byType形式,是就執行byType自動裝配代碼。那麼首先看一下第7行的byName代碼實現:
1 protected void autowireByName(
2 String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
3
4 String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
5 for (String propertyName : propertyNames) {
6 if (containsBean(propertyName)) {
7 Object bean = getBean(propertyName);
8 pvs.add(propertyName, bean);
9 registerDependentBean(propertyName, beanName);
10 if (logger.isDebugEnabled()) {
11 logger.debug("Added autowiring by name from bean name '" + beanName +
12 "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
13 }
14 }
15 else {
16 if (logger.isTraceEnabled()) {
17 logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
18 "' by name: no matching bean found");
19 }
20 }
21 }
22 }
篇幅問題,代碼不一層層跟了,邏輯梳理一下:
其余代碼都是一些打日志的,沒什麼好說的。
byType源碼實現
上面說了byName的源碼實現,接下來看一下byType源碼實現:
1 protected void autowireByType(
2 String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
3
4 TypeConverter converter = getCustomTypeConverter();
5 if (converter == null) {
6 converter = bw;
7 }
8
9 Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);
10 String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
11 for (String propertyName : propertyNames) {
12 try {
13 PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
14 // Don't try autowiring by type for type Object: never makes sense,
15 // even if it technically is a unsatisfied, non-simple property.
16 if (!Object.class.equals(pd.getPropertyType())) {
17 MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
18 // Do not allow eager init for type matching in case of a prioritized post-processor.
19 boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
20 DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
21 Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
22 if (autowiredArgument != null) {
23 pvs.add(propertyName, autowiredArgument);
24 }
25 for (String autowiredBeanName : autowiredBeanNames) {
26 registerDependentBean(autowiredBeanName, beanName);
27 if (logger.isDebugEnabled()) {
28 logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
29 propertyName + "' to bean named '" + autowiredBeanName + "'");
30 }
31 }
32 autowiredBeanNames.clear();
33 }
34 }
35 catch (BeansException ex) {
36 throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
37 }
38 }
39 }
前面一樣,到第10行都是找到Bean中屬性是對象類型的屬性。
接著就是遍歷一下PropertyName,獲取PropertyName對應的屬性描述,注意一下16行的判斷及其對應的注釋:不要嘗試自動裝配Object類型,這沒有任何意義,即使從技術角度看它是一個非簡單的對象屬性。
第18行~第20行跳過(沒有太明白是干什麼的),byType實現的源碼主要在第21行的方法resolveDependency中,這個方法是AbstractAutowireCapableBeanFactory類的實現類DefaultListableBeanFactory中的方法:
1 public Object resolveDependency(DependencyDescriptor descriptor, String beanName,
2 Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
3
4 descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
5 if (descriptor.getDependencyType().equals(ObjectFactory.class)) {
6 return new DependencyObjectFactory(descriptor, beanName);
7 }
8 else if (descriptor.getDependencyType().equals(javaxInjectProviderClass)) {
9 return new DependencyProviderFactory().createDependencyProvider(descriptor, beanName);
10 }
11 else {
12 return doResolveDependency(descriptor, descriptor.getDependencyType(), beanName, autowiredBeanNames, typeConverter);
13 }
14 }
這裡判斷一下要自動裝配的屬性是ObjectFactory.class還是javaxInjectProviderClass還是其他的,我們裝配的是其他的,看一下12行的代碼實現:
1 protected Object doResolveDependency(DependencyDescriptor descriptor, Class<?> type, String beanName,
2 Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
3
4 Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
5 if (value != null) {
6 if (value instanceof String) {
7 String strVal = resolveEmbeddedValue((String) value);
8 BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
9 value = evaluateBeanDefinitionString(strVal, bd);
10 }
11 TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
12 return converter.convertIfNecessary(value, type);
13 }
14
15 if (type.isArray()) {
16 ...
17 }
18 else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
19 ...
20 }
21 else if (Map.class.isAssignableFrom(type) && type.isInterface()) {
22 ...
23 }
24 else {
25 Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
26 if (matchingBeans.isEmpty()) {
27 if (descriptor.isRequired()) {
28 raiseNoSuchBeanDefinitionException(type, "", descriptor);
29 }
30 return null;
31 }
32 if (matchingBeans.size() > 1) {
33 String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor);
34 if (primaryBeanName == null) {
35 throw new NoSuchBeanDefinitionException(type, "expected single matching bean but found " +
36 matchingBeans.size() + ": " + matchingBeans.keySet());
37 }
38 if (autowiredBeanNames != null) {
39 autowiredBeanNames.add(primaryBeanName);
40 }
41 return matchingBeans.get(primaryBeanName);
42 }
43 // We have exactly one match.
44 Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
45 if (autowiredBeanNames != null) {
46 autowiredBeanNames.add(entry.getKey());
47 }
48 return entry.getValue();
49 }
50 }
第四行結果是null不看了,為了簡化代碼Array裝配、Collection裝配、Map裝配的代碼都略去了,重點看一下普通屬性的裝配。首先是第25行獲取一下自動裝配的候選者:
1 protected Map<String, Object> findAutowireCandidates(
2 String beanName, Class requiredType, DependencyDescriptor descriptor) {
3
4 String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
5 this, requiredType, true, descriptor.isEager());
6 Map<String, Object> result = new LinkedHashMap<String, Object>(candidateNames.length);
7 for (Class autowiringType : this.resolvableDependencies.keySet()) {
8 if (autowiringType.isAssignableFrom(requiredType)) {
9 Object autowiringValue = this.resolvableDependencies.get(autowiringType);
10 autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
11 if (requiredType.isInstance(autowiringValue)) {
12 result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
13 break;
14 }
15 }
16 }
17 for (String candidateName : candidateNames) {
18 if (!candidateName.equals(beanName) && isAutowireCandidate(candidateName, descriptor)) {
19 result.put(candidateName, getBean(candidateName));
20 }
21 }
22 return result;
23 }
代碼邏輯整理一下:
這樣,拿到所有待裝配對象的實現類或者子類的候選者,組成一個Map,Key為beanName,Value為具體的Bean。接著回看獲取Bean之後的邏輯:
1 Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
2 if (matchingBeans.isEmpty()) {
3 if (descriptor.isRequired()) {
4 raiseNoSuchBeanDefinitionException(type, "", descriptor);
5 }
6 return null;
7 }
8 if (matchingBeans.size() > 1) {
9 String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor);
10 if (primaryBeanName == null) {
11 throw new NoSuchBeanDefinitionException(type, "expected single matching bean but found " +
12 matchingBeans.size() + ": " + matchingBeans.keySet());
13 }
14 if (autowiredBeanNames != null) {
15 autowiredBeanNames.add(primaryBeanName);
16 }
17 return matchingBeans.get(primaryBeanName);
18 }
19 // We have exactly one match.
20 Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
21 if (autowiredBeanNames != null) {
22 autowiredBeanNames.add(entry.getKey());
23 }
24 ...
25 }
整理一下邏輯:
通過這樣一整個流程,實現了byType自動裝配,byType自動裝配流程比較長,中間細節比較多,還需要多看看才能弄明白。
最後注意一點,即所有待注入的PropertyName-->PropertyValue映射拿到之後都只是放在MutablePropertyValues中,最後由AbstractPropertyAccessor類的setPropertyValues方法遍歷並進行逐一注入。
通過FactoryBean獲取Bean實例源碼實現
我們知道可以通過實現FactoryBean接口,重寫getObject()方法實現個性化定制Bean的過程,這部分我們就來看一下Spring源碼是如何實現通過FactoryBean獲取Bean實例的。代碼直接定位到AbstractBeanFactory的doGetBean方法創建單例Bean這部分:
1 // Create bean instance.
2 if (mbd.isSingleton()) {
3 sharedInstance = getSingleton(beanName, new ObjectFactory() {
4 public Object getObject() throws BeansException {
5 try {
6 return createBean(beanName, mbd, args);
7 }
8 catch (BeansException ex) {
9 // Explicitly remove instance from singleton cache: It might have been put there
10 // eagerly by the creation process, to allow for circular reference resolution.
11 // Also remove any beans that received a temporary reference to the bean.
12 destroySingleton(beanName);
13 throw ex;
14 }
15 }
16 });
17 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
18 }
FactoryBean首先是個Bean且被實例化出來成為一個對象之後才能調用getObject()方法,因此還是會執行第3行~第16行的代碼,這段代碼之前分析過了就不說了。之後執行第17行的方法:
1 protected Object getObjectForBeanInstance(
2 Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
3
4 // Don't let calling code try to dereference the factory if the bean isn't a factory.
5 if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
6 throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
7 }
8
9 // Now we have the bean instance, which may be a normal bean or a FactoryBean.
10 // If it's a FactoryBean, we use it to create a bean instance, unless the
11 // caller actually wants a reference to the factory.
12 if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
13 return beanInstance;
14 }
15
16 Object object = null;
17 if (mbd == null) {
18 object = getCachedObjectForFactoryBean(beanName);
19 }
20 if (object == null) {
21 // Return bean instance from factory.
22 FactoryBean factory = (FactoryBean) beanInstance;
23 // Caches object obtained from FactoryBean if it is a singleton.
24 if (mbd == null && containsBeanDefinition(beanName)) {
25 mbd = getMergedLocalBeanDefinition(beanName);
26 }
27 boolean synthetic = (mbd != null && mbd.isSynthetic());
28 object = getObjectFromFactoryBean(factory, beanName, !synthetic);
29 }
30 return object;
31 }
首先第5行~第7行判斷一下是否beanName以"&"開頭並且不是FactoryBean的實現類,不滿足則拋異常,因為beanName以"&"開頭是FactoryBean的實現類bean定義的一個特征。
接著判斷第12行~第14行,如果:
這兩種情況,都直接把生成的bean對象返回出去,不會執行余下的流程。
最後流程走到第16行~第30行,最終調用getObject()方法實現個性化定制bean,先執行第28行的方法:
1 protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) {
2 if (factory.isSingleton() && containsSingleton(beanName)) {
3 synchronized (getSingletonMutex()) {
4 Object object = this.factoryBeanObjectCache.get(beanName);
5 if (object == null) {
6 object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
7 this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
8 }
9 return (object != NULL_OBJECT ? object : null);
10 }
11 }
12 else {
13 return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
14 }
15 }
第1行~第11行的代碼與第12行~第13行的代碼最終都是一樣的,調用了如下一段:
1 private Object doGetObjectFromFactoryBean(
2 final FactoryBean factory, final String beanName, final boolean shouldPostProcess)
3 throws BeanCreationException {
4
5 Object object;
6 try {
7 if (System.getSecurityManager() != null) {
8 AccessControlContext acc = getAccessControlContext();
9 try {
10 object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
11 public Object run() throws Exception {
12 return factory.getObject();
13 }
14 }, acc);
15 }
16 catch (PrivilegedActionException pae) {
17 throw pae.getException();
18 }
19 }
20 else {
21 object = factory.getObject();
22 }
23 }
24 catch (FactoryBeanNotInitializedException ex) {
25 throw new BeanCurrentlyInCreationException(beanName, ex.toString());
26 }
27 catch (Throwable ex) {
28 throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
29 }
30
31 // Do not accept a null value for a FactoryBean that's not fully
32 // initialized yet: Many FactoryBeans just return null then.
33 if (object == null && isSingletonCurrentlyInCreation(beanName)) {
34 throw new BeanCurrentlyInCreationException(
35 beanName, "FactoryBean which is currently in creation returned null from getObject");
36 }
37
38 if (object != null && shouldPostProcess) {
39 try {
40 object = postProcessObjectFromFactoryBean(object, beanName);
41 }
42 catch (Throwable ex) {
43 throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);
44 }
45 }
46
47 return object;
48 }
第12行和第21行的代碼,都一樣,最終調用getObject()方法獲取對象。回過頭去看之前的getObjectFromFactoryBean方法,雖然if...else...邏輯最終都是調用了以上的方法,但是區別在於: