在Spring Framework源代码解析之IOC容器(一)和Spring Framework源代码解析之IOC容器(二),我们对Spring IOC做了简单介绍以及熟悉了一些支持IOC的关键类,本文将对IOC的依赖注入特性进行解析,欢迎指正。
载入和注册
在上文中,我们介绍到XmlBeanFactory对资源文件的载入,并最后引出了一个高帅富——ApplicationContext。接着上文来看,其实我们平时最常用的是Application,因为它不仅具备BeanFactory的全部能力,还为应用程序提供了很多的便利,上文已经说过了,它继承了很多父类,使它可以具备支持国际化、支持多方式定义资源,支持事件等。我们可以认为BeanFactory和Application是两个层面的IOC容器,而我们平时开发应用程序就是使用Application。Application有很多抽象子类,如AbstractApplicationContext,在该抽象子类下又有很多具体的实现类,如FileSystemXmlApplicationContext、ClassPathXmlApplicationContext等。我们以FileSystemXmlApplicationContext为例,来看看它载入和注册资源的过程。
首先通过FileSystemXmlApplicationContext来建立IOC容器:
ApplicationContext = new FileSystemXmlApplicationContext(xmlPath);调用构造函数:
/**
* Create a new FileSystemXmlApplicationContext, loading the definitions
* from the given XML files and automatically refreshing the context.
* @param configLocations array of file paths
* @throws BeansException if context creation failed
*/
public FileSystemXmlApplicationContext(String... configLocations) throws BeansException {
this(configLocations, true, null);
}实际调用:
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}注意方法refresh(),这里使用了一个“模板方法”的设计模式,refresh()是一个模板方法,具体实现在FileSystemXmlApplicationContext的若干级父类AbstractXmlApplicationContext中:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
synchronized (this.activeMonitor) {
this.active = true;
}
// 这里需要子类来协助完成资源位置定义,bean 载入和向 IOC 容器注册的过程
refreshBeanFactory();
............
}refresh()方法包含了整个IOC容器的初始化过程,资源的定位由refreshBeanFactory()来实现,而在AbstractXmlApplicationContext中定义了对资源的读取过程,默认由 XmlBeanDefinitionReader 来读取:
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {
// 这里使用 XMLBeanDefinitionReader 来载入 bean 定义信息的 XML 文件
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//这里配置 reader 的环境,其中 ResourceLoader 是我们用来定位 bean 定义信息资源位置的
///因为上下文本身实现了 ResourceLoader 接口,所以可以直接把上下文作为 ResourceLoader 传递给 XmlBeanDefi
nitionReader
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
initBeanDefinitionReader(beanDefinitionReader);
//这里转到定义好的 XmlBeanDefinitionReader 中对载入 bean 信息进行处理
loadBeanDefinitions(beanDefinitionReader);
}转到beanDefinitionReader中进行处理:
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOExcepti
on {
Resource[] configResources = getConfigResources();
if (configResources != null) {
//调用 XmlBeanDefinitionReader 来载入 bean 定义信息。
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}完成了载入,我们来分析注册,来到DefaultListableBeanFactory中,它通过HashMap来持有载入的BeanDefinition:
/** Map of bean definition objects, keyed by bean name */
private final Map<string ,="" beandefinition=""> beanDefinitionMap = new ConcurrentHashMap<string ,="" beandefinition="">();</string></string>跟踪代码,找到注册的具体实现类DefaultListableBeanFactoy:
//---------------------------------------------------------------------
// Implementation of BeanDefinitionRegistry interface
//---------------------------------------------------------------------
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
synchronized (this.beanDefinitionMap) {
//这里检查是不是有名字相同的BeanDefinition已经在IOC容器中注册,如果有但不允许覆盖则抛出异常
Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
}
else {
this.beanDefinitionNames.add(beanName);
this.frozenBeanDefinitionNames = null;
}
this.beanDefinitionMap.put(beanName, beanDefinition);
resetBeanDefinition(beanName);
}
}完成了注册,此时我们就是从容器中使用对象了,万事具备只欠getBean了。
依赖注入
我们记得在BeanFactory中有一个getBean方法,它其实就是触发依赖注入的入口,getBean的实现我们具体看看DefaultListableBeanFactory的父类AbstractBeanFactory,看看其中getBean的是如何实现的:
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}接着看doGetBean:
1. protected <T> T doGetBean(final String name, final Class<T> requiredType,2. final Object[] args, boolean typeCheckOnly) throws BeansException { 3: 4: final String beanName = transformedBeanName(name); 5: Object bean; 6: 7: // Eagerly check singleton cache for manually registered singletons. 8: // 先从缓存里面取,处理已经被创建过的单件模式的bean,对这种bean的获取不需要重复的创建 9: Object sharedInstance = getSingleton(beanName); 10: if (sharedInstance != null && args == null) { 11: if (logger.isDebugEnabled()) { 12: if (isSingletonCurrentlyInCreation(beanName)) { 13: logger.debug("Returning eagerly cached instance of singleton bean '" 14: + beanName 15: + "' that is not fully initialized yet - a consequence of a circular reference"); 16: } else { 17: logger.debug("Returning cached instance of singleton bean '" 18: + beanName + "'"); 19: } 20: } 21: bean = getObjectForBeanInstance(sharedInstance, name, beanName, 22: null); 23: } 24: 25: else { 26: // Fail if we're already creating this bean instance: 27: // We're assumably within a circular reference. 28: if (isPrototypeCurrentlyInCreation(beanName)) { 29: throw new BeanCurrentlyInCreationException(beanName); 30: } 31: 32: // Check if bean definition exists in this factory. 33: BeanFactory parentBeanFactory = getParentBeanFactory(); 34: if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { 35: // Not found -> check parent. 36: String nameToLookup = originalBeanName(name); 37: if (args != null) { 38: // Delegation to parent with explicit args. 39: return (T) parentBeanFactory.getBean(nameToLookup, args); 40: } else { 41: // No args -> delegate to standard getBean method. 42: return parentBeanFactory 43: .getBean(nameToLookup, requiredType); 44: } 45: } 46: 47: if (!typeCheckOnly) { 48: markBeanAsCreated(beanName); 49: } 50: // 这里根据bean的名字取得BeanDefinition 51: final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 52: checkMergedBeanDefinition(mbd, beanName, args); 53: 54: // Guarantee initialization of beans that the current bean depends 55: // on. 56: // 取当前bean的所有依赖的bean,这样会触发getBean的递归调用,直至取到一个没有任何依赖的bean为止 57: String[] dependsOn = mbd.getDependsOn(); 58: if (dependsOn != null) { 59: for (String dependsOnBean : dependsOn) { 60: getBean(dependsOnBean); 61: registerDependentBean(dependsOnBean, beanName); 62: } 63: } 64: 65: // Create bean instance. 66: // 这里创建单例的实例,调用createBean方法 67: if (mbd.isSingleton()) { 68: sharedInstance = getSingleton(beanName, 69: new ObjectFactory<Object>() { 70: public Object getObject() throws BeansException { 71: try { 72: return createBean(beanName, mbd, args); 73: } catch (BeansException ex) { 74: // Explicitly remove instance from singleton 75: // cache: It might have been put there 76: // eagerly by the creation process, to allow 77: // for circular reference resolution. 78: // Also remove any beans that received a 79: // temporary reference to the bean. 80: destroySingleton(beanName); 81: throw ex; 82: } 83: } 84: }); 85: bean = getObjectForBeanInstance(sharedInstance, name, beanName, 86: mbd); 87: } 88: // 这里则是创建prototype bean的地方 89: else if (mbd.isPrototype()) { 90: // It's a prototype -> create a new instance. 91: Object prototypeInstance = null; 92: try { 93: beforePrototypeCreation(beanName); 94: prototypeInstance = createBean(beanName, mbd, args); 95: } finally { 96: afterPrototypeCreation(beanName); 97: } 98: bean = getObjectForBeanInstance(prototypeInstance, name, 99: beanName, mbd); 100: } 101: 102: else { 103: String scopeName = mbd.getScope(); 104: final Scope scope = this.scopes.get(scopeName); 105: if (scope == null) { 106: throw new IllegalStateException( 107: "No Scope registered for scope '" + scopeName + "'"); 108: } 109: try { 110: Object scopedInstance = scope.get(beanName, 111: new ObjectFactory<Object>() { 112: public Object getObject() throws BeansException { 113: beforePrototypeCreation(beanName); 114: try { 115: return createBean(beanName, mbd, args); 116: } finally { 117: afterPrototypeCreation(beanName); 118: } 119: } 120: }); 121: bean = getObjectForBeanInstance(scopedInstance, name, 122: beanName, mbd); 123: } catch (IllegalStateException ex) { 124: throw new BeanCreationException( 125: beanName, 126: "Scope '" 127: + scopeName 128: + "' is not active for the current thread; " 129: + "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", 130: ex); 131: } 132: } 133: } 134: 135: // Check if required type matches the type of the actual bean instance. 136: // 这里对创建出来bean进行类型的检查,如果没有问题,就返回这个新创建的bean 137: if (requiredType != null && bean != null 138: && !requiredType.isAssignableFrom(bean.getClass())) { 139: try { 140: return getTypeConverter() 141: .convertIfNecessary(bean, requiredType); 142: } catch (TypeMismatchException ex) { 143: if (logger.isDebugEnabled()) { 144: logger.debug( 145: "Failed to convert bean '" + name 146: + "' to required type [" 147: + ClassUtils.getQualifiedName(requiredType) 148: + "]", ex); 149: } 150: throw new BeanNotOfRequiredTypeException(name, requiredType, 151: bean.getClass()); 152: } 153: } 154: return (T) bean; 155: }具体创建对象在createBean里面,来看看createBean:
1: protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) 2: throws BeanCreationException { 3: 4: if (logger.isDebugEnabled()) { 5: logger.debug("Creating instance of bean '" + beanName + "'"); 6: } 7: // Make sure bean class is actually resolved at this point. 8: resolveBeanClass(mbd, beanName); 9: 10: // Prepare method overrides. 11: try { 12: mbd.prepareMethodOverrides(); 13: } 14: catch (BeanDefinitionValidationException ex) { 15: throw new BeanDefinitionStoreException(mbd.getResourceDescription(), 16: beanName, "Validation of method overrides failed", ex); 17: } 18: 19: try { 20: // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. 21: Object bean = resolveBeforeInstantiation(beanName, mbd); 22: if (bean != null) { 23: return bean; 24: } 25: } 26: catch (Throwable ex) { 27: throw new BeanCreationException(mbd.getResourceDescription(), beanName, 28: "BeanPostProcessor before instantiation of bean failed", ex); 29: } 30: //这里是创建bean的调用 31: Object beanInstance = doCreateBean(beanName, mbd, args); 32: if (logger.isDebugEnabled()) { 33: logger.debug("Finished creating instance of bean '" + beanName + "'"); 34: } 35: return beanInstance; 36: }又看doCreateBean,^_^遭不住啊。。
1: protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) { 2: // Instantiate the bean. 3: BeanWrapper instanceWrapper = null; 4: if (mbd.isSingleton()) { 5: instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); 6: } 7: if (instanceWrapper == null) { 8: instanceWrapper = createBeanInstance(beanName, mbd, args); 9: } 10: ......... 11: 12: }具体创建对象的方法是createBeanInstance:
1: protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { 2: // Make sure bean class is actually resolved at this point. 3: Class beanClass = resolveBeanClass(mbd, beanName); 4: 5: if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { 6: throw new BeanCreationException(mbd.getResourceDescription(), beanName, 7: "Bean class isn't public, and non-public access not allowed: " + beanClass.getName()); 8: } 9: //这里使用工厂方法对bean进行实例化 10: if (mbd.getFactoryMethodName() != null) { 11: return instantiateUsingFactoryMethod(beanName, mbd, args); 12: } 13: 14: // Shortcut when re-creating the same bean... 15: boolean resolved = false; 16: boolean autowireNecessary = false; 17: if (args == null) { 18: synchronized (mbd.constructorArgumentLock) { 19: if (mbd.resolvedConstructorOrFactoryMethod != null) { 20: resolved = true; 21: autowireNecessary = mbd.constructorArgumentsResolved; 22: } 23: } 24: } 25: if (resolved) { 26: if (autowireNecessary) { 27: return autowireConstructor(beanName, mbd, null, null); 28: } 29: else { 30: return instantiateBean(beanName, mbd); 31: } 32: } 33: 34: // Need to determine the constructor... 35: //使用构造函数进行实例化 36: Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); 37: if (ctors != null || 38: mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || 39: mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { 40: return autowireConstructor(beanName, mbd, ctors, args); 41: } 42: 43: // No special handling: simply use no-arg constructor. 44: //使用默认的构造函数对bean进行实例化 45: return instantiateBean(beanName, mbd); 46: }来看看使用默认的构造函数对bean进行实例化的代码instantiateBean:
1: protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { 2: try { 3: //使用默认的实例化策略对bean进行实例化,默认的实例化策略是CglibSubclassingInstantiationStrategy,也就是用cglib来对bean进行实例化 4: Object beanInstance; 5: final BeanFactory parent = this; 6: if (System.getSecurityManager() != null) { 7: beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() { 8: public Object run() { 9: return getInstantiationStrategy().instantiate(mbd, beanName, parent); 10: } 11: }, getAccessControlContext()); 12: } 13: else { 14: beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); 15: } 16: BeanWrapper bw = new BeanWrapperImpl(beanInstance); 17: initBeanWrapper(bw); 18: return bw; 19: } 20: catch (Throwable ex) { 21: throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); 22: } 23: }这里用cglib对bean进行实例化,cglib是一个常用的字节码生成器的类库,它提供了一系列的API来提供java字节码生成和转换的功能,如果有兴趣可以查看cglib的使用文档。另外生成bean的策略还有很多种,这里只是选了最常用的方法来介绍。至此,bean实例创建过程就算完成了,然后通过populateBean方法将创建好的实例的依赖关系设置好,最终完成依赖注入的过程,由于篇幅关系这里就不详细列举了,populateBean方法可以在AbstractAutowireCapableBeanFactory中找到。
小结
自己对Spring IOC代码的学习暂时就到这里,要搞懂一个特性,确实需要花费很大的功夫,Spring代码量比较大,而且各个特性之间又有交叉,要梳理清楚不是件容易的事,不过回头来看自己还是有收获的,希望对看它的朋友也有一点收获。
