SpringIoC依赖注入的过程(二)

SpringIoC依赖注入的过程(二)

   上文讲到spring通过AbstractAutowireCapableBeanFactory的doCreateBean方法来创建并且初始化一个bean,doCreateBean首先生成一个未初始化的bean,然后再对它进行依赖注入、属性解析以及回调bean的方法等等。本文将继续讲解spring是如何做到这些的。
   衔接上文,分析doCreateBean的源码,紧接着bean创建后的第一段代码如下:
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				mbd.postProcessed = true;
			}
		}
   具体做了什么事情,跟到applyMergedBeanDefinitionPostProcessors方法中看
	protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class beanType, String beanName)
			throws BeansException {

		try {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof MergedBeanDefinitionPostProcessor) {
					MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
					bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
				}
			}
		}
		catch (Exception ex) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Post-processing failed of bean type [" + beanType + "] failed", ex);
		}
	}
   上面的 applyMergedBeanDefinitionPostProcessors方法中,调用了所有MergedBeanDefinitionPostProcessor后置处理器的postProcessMergedBeanDefinition。那么,MergedBeanDefinitionPostProcessor有哪些呢?CommonAnnotationBeanPostProcessor是其中一个,看看它执行了什么操作
	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
		if (beanType != null) {
			InjectionMetadata metadata = findResourceMetadata(beanType);
			metadata.checkConfigMembers(beanDefinition);
		}
	}
    CommonAnnotationBeanPostProcessor又调用了父类的postProcessMergedBeanDefinition方法,它的父类就是InitDestroyAnnotationBeanPostProcessor。从名字上可以看出,它就是管理通过标注声明的初始化以及销毁bean的方法的。它的postProcessMergedBeanDefinition方法是这样的
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		if (beanType != null) {
			LifecycleMetadata metadata = findLifecycleMetadata(beanType);
			metadata.checkConfigMembers(beanDefinition);
		}
	}
    根据bean的类型找到LifecycleMetadata,然后用它配置BeanDefinition。 LifecycleMetadata是什么呢,我们先来看看它是怎么来的
	private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
		if (this.lifecycleMetadataCache == null) {
			// Happens after deserialization, during destruction...
			return buildLifecycleMetadata(clazz);
		}
		// Quick check on the concurrent map first, with minimal locking.
		LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
		if (metadata == null) {
			synchronized (this.lifecycleMetadataCache) {
				metadata = this.lifecycleMetadataCache.get(clazz);
				if (metadata == null) {
					metadata = buildLifecycleMetadata(clazz);
					this.lifecycleMetadataCache.put(clazz, metadata);
				}
				return metadata;
			}
		}
		return metadata;
	}

	private LifecycleMetadata buildLifecycleMetadata(Class<?> clazz) {
		final boolean debug = logger.isDebugEnabled();
		LinkedList<LifecycleElement> initMethods = new LinkedList<LifecycleElement>();
		LinkedList<LifecycleElement> destroyMethods = new LinkedList<LifecycleElement>();
		Class<?> targetClass = clazz;

		do {
			LinkedList<LifecycleElement> currInitMethods = new LinkedList<LifecycleElement>();
			LinkedList<LifecycleElement> currDestroyMethods = new LinkedList<LifecycleElement>();
			for (Method method : targetClass.getDeclaredMethods()) {
				if (this.initAnnotationType != null) {
					if (method.getAnnotation(this.initAnnotationType) != null) {
						LifecycleElement element = new LifecycleElement(method);
						currInitMethods.add(element);
						if (debug) {
							logger.debug("Found init method on class [" + clazz.getName() + "]: " + method);
						}
					}
				}
				if (this.destroyAnnotationType != null) {
					if (method.getAnnotation(this.destroyAnnotationType) != null) {
						currDestroyMethods.add(new LifecycleElement(method));
						if (debug) {
							logger.debug("Found destroy method on class [" + clazz.getName() + "]: " + method);
						}
					}
				}
			}
			initMethods.addAll(0, currInitMethods);
			destroyMethods.addAll(currDestroyMethods);
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class);

		return new LifecycleMetadata(clazz, initMethods, destroyMethods);
	}
   同样,Spring对 LifecycleMetadata做了缓存,并且同样使用了类似于双重检查机制的单例模式,先判断缓存中有没有,若没有先对线程安全的map加锁,然后再次查看缓存中有没有,如果没有才去创建。创建LifecycleMetadata 的过程是怎样的呢?它由两个方法列表构成,一个是initMethods,另一个是destroyMethods。这两个方法列表是什么呢?就是在bean中声明了PostConstructPreDestroy标注的方法。buildLifecycleMetadata方法不仅寻找当前类声明PostConstructPreDestroy标注的方法,还会循环的查找父类中声明了这两个标注的方法。得到了LifecycleMetadata后它对BeanDefinition做了什么呢,来看LifecycleMetadata的checkConfigMembers方法的代码:
		public void checkConfigMembers(RootBeanDefinition beanDefinition) {
			synchronized(this.initMethods) {
				for (Iterator<LifecycleElement> it = this.initMethods.iterator(); it.hasNext();) {
					String methodIdentifier = it.next().getIdentifier();
					if (!beanDefinition.isExternallyManagedInitMethod(methodIdentifier)) {
						beanDefinition.registerExternallyManagedInitMethod(methodIdentifier);
					}
					else {
						it.remove();
					}
				}
			}
			synchronized(this.destroyMethods) {
				for (Iterator<LifecycleElement> it = this.destroyMethods.iterator(); it.hasNext();) {
					String methodIdentifier = it.next().getIdentifier();
					if (!beanDefinition.isExternallyManagedDestroyMethod(methodIdentifier)) {
						beanDefinition.registerExternallyManagedDestroyMethod(methodIdentifier);
					}
					else {
						it.remove();
					}
				}
			}
		}
    简单的概括一下上面方法的行为就是把所有的 initMethods和 destroyMethods注册到BeanDefinition中去备用,什么时候用,后面会说到。说了这么多,才把InitDestroyAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法说完。接下来看看它的子类在父类处理完之后它又做了些啥。为了方便,再贴一边代码
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
		if (beanType != null) {
			InjectionMetadata metadata = findResourceMetadata(beanType);
			metadata.checkConfigMembers(beanDefinition);
		}
	}
   有了刚才的基础,一切都好理解了。它去寻找InjectionMetadata ,然后注册到BeanDefinition中备用。截止目前终于出现了注入的字眼,跟到findResourceMetadata中去看看它到底找到了什么。
	private InjectionMetadata findResourceMetadata(final Class<?> clazz) {
		// Quick check on the concurrent map first, with minimal locking.
		InjectionMetadata metadata = this.injectionMetadataCache.get(clazz);
		if (metadata == null) {
			synchronized (this.injectionMetadataCache) {
				metadata = this.injectionMetadataCache.get(clazz);
				if (metadata == null) {
					LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
					Class<?> targetClass = clazz;

					do {
						LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<InjectionMetadata.InjectedElement>();
						for (Field field : targetClass.getDeclaredFields()) {
							if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
								if (Modifier.isStatic(field.getModifiers())) {
									throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
								}
								currElements.add(new WebServiceRefElement(field, null));
							}
							else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) {
								if (Modifier.isStatic(field.getModifiers())) {
									throw new IllegalStateException("@EJB annotation is not supported on static fields");
								}
								currElements.add(new EjbRefElement(field, null));
							}
							else if (field.isAnnotationPresent(Resource.class)) {
								if (Modifier.isStatic(field.getModifiers())) {
									throw new IllegalStateException("@Resource annotation is not supported on static fields");
								}
								if (!ignoredResourceTypes.contains(field.getType().getName())) {
									currElements.add(new ResourceElement(field, null));
								}
							}
						}
						for (Method method : targetClass.getDeclaredMethods()) {
							method = BridgeMethodResolver.findBridgedMethod(method);
							Method mostSpecificMethod = BridgeMethodResolver.findBridgedMethod(ClassUtils.getMostSpecificMethod(method, clazz));
							if (method.equals(mostSpecificMethod)) {
								if (webServiceRefClass != null && method.isAnnotationPresent(webServiceRefClass)) {
									if (Modifier.isStatic(method.getModifiers())) {
										throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
									}
									if (method.getParameterTypes().length != 1) {
										throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
									}
									PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
									currElements.add(new WebServiceRefElement(method, pd));
								}
								else if (ejbRefClass != null && method.isAnnotationPresent(ejbRefClass)) {
									if (Modifier.isStatic(method.getModifiers())) {
										throw new IllegalStateException("@EJB annotation is not supported on static methods");
									}
									if (method.getParameterTypes().length != 1) {
										throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
									}
									PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
									currElements.add(new EjbRefElement(method, pd));
								}
								else if (method.isAnnotationPresent(Resource.class)) {
									if (Modifier.isStatic(method.getModifiers())) {
										throw new IllegalStateException("@Resource annotation is not supported on static methods");
									}
									Class<?>[] paramTypes = method.getParameterTypes();
									if (paramTypes.length != 1) {
										throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
									}
									if (!ignoredResourceTypes.contains(paramTypes[0].getName())) {
										PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
										currElements.add(new ResourceElement(method, pd));
									}
								}
							}
						}
						elements.addAll(0, currElements);
						targetClass = targetClass.getSuperclass();
					}
					while (targetClass != null && targetClass != Object.class);

					metadata = new InjectionMetadata(clazz, elements);
					this.injectionMetadataCache.put(clazz, metadata);
				}
			}
		}
		return metadata;
	}
   还是原来的配方,还是原来的味道。不同的只是查找和注册的内容不同,前两个处理的是web service相关的东西,本人没用过,也就不详细说了。最后一个处理的是 Resource 标注,又发现了我们要找的东西了。我们继续寻找,还有哪些 MergedBeanDefinitionPostProcessor,都注册哪些东西?AutowiredAnnotationBeanPostProcessor注册了声明了 Autowired 标注的字段和方法。AbstractApplicationContext的内部类ApplicationListenerDetector向AbstractApplicationContext注册了单例bean的名字。常用的也就这么几个,下面是在我的工程里找出的所有MergedBeanDefinitionPostProcessor的子类。
                                     
   说了这么多,才说完doCreateBean中的applyMergedBeanDefinitionPostProcessors,执行这个方法找到了需要注入的声明了Autowired标注和Resource标注的字段和方法,为下一步的注入做了准备。后续的操作下一篇文章继续。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值