简介: 介绍Spring IOC 的实现原理以及IOC容器的启动流程。
关键词: Spring IOC;IOC原理;IOC源码;IOC启动;
控制反转(IoC) 在传统的 Java 应用中,一个类想要调用另一个类中的属性或方法,通常会先在其代码中通过 new Object() 的方式将后者的对象创建出来,然后才能实现属性或方法的调用。为了方便理解和描述,我们可以将前者称为“调用者”,将后者称为“被调用者”。也就是说,调用者掌握着被调用者对象创建的控制权。
但在 Spring 应用中,Java 对象创建的控制权是掌握在 IoC 容器手里的,其大致步骤如下。
开发人员通过 XML 配置文件、注解、Java 配置类等方式,对 Java 对象进行定义,例如在 XML 配置文件中使用 标签、在 Java 类上使用 @Component 注解等。
Spring 启动时,IoC 容器会自动根据对象定义,将这些对象创建并管理起来。这些被 IoC 容器创建并管理的对象被称为 Spring Bean。
当我们想要使用某个 Bean 时,可以直接从 IoC 容器中获取(例如通过 ApplicationContext 的 getBean() 方法),而不需要手动通过代码(例如 new Obejct() 的方式)创建。
IoC 带来的最大改变不是代码层面的,而是从思想层面上发生了“主从换位”的改变。原本调用者是主动的一方,它想要使用什么资源就会主动出击,自己创建;但在 Spring 应用中,IoC 容器掌握着主动权,调用者则变成了被动的一方,被动的等待 IoC 容器创建它所需要的对象(Bean)。
这个过程在职责层面发生了控制权的反转,把原本调用者通过代码实现的对象的创建,反转给 IoC 容器来帮忙实现,因此我们将这个过程称为 Spring 的“控制反转”。
IOC有一个专门的容器来创建这些对象,由IOC容器来控制对象的创建,依赖对象也是容器帮忙查找创建并进行注入,对象只是被动的接受,依赖对象的获取被反转了。它还有一个更加形象的名字叫 依赖注入。
依赖注入方式:
IOC容器的设计与实现有两种:BeanFactory 和ApplicationContext :
实现了BeanFactory接口的简单容器系列,只是实现了容器最基本的功能。
Applic ationContext应用上下文,作为容器的高级形态存在。除了具有基本的功能外,还增加了许多面向框架的特性,同时对应用环境做了许多适配。
BeanFactory BeanFactory为IOC容器具体实现指定了基本的规范,它有三个子类,ListableBeanFactory、HierarchicalBeanFactory和AutowireCapableBeanFactory接口。但是它们最终生成了一个默认的实现类DefaultListableBeanFactory。类的继承关系如下:
BeanFactory接口中的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public interface BeanFactory { String FACTORY_BEAN_PREFIX = "&" ; Object getBean (String var1) throws BeansException ; <T> T getBean (String var1, Class<T> var2) throws BeansException ; <T> T getBean (Class<T> var1) throws BeansException ; Object getBean (String var1, Object... var2) throws BeansException ; boolean containsBean (String var1) ; boolean isSingleton (String var1) throws NoSuchBeanDefinitionException ; boolean isPrototype (String var1) throws NoSuchBeanDefinitionException ; boolean isTypeMatch (String var1, Class<?> var2) throws NoSuchBeanDefinitionException ; Class<?> getType(String var1) throws NoSuchBeanDefinitionException; String[] getAliases(String var1); }
BeanFactory并不关心bean是如何定义、怎样被加载。当我们需要bean的时候,直接来取就可以了。对于工厂来说,我只需要关心有没有产品,对于产品是怎么产生,怎么制作的,那是工人干的事,工厂并不关心。定义的都是最核心的接口,如getBean()
从容器中获取实例。
ApplicationContext ApplicationContext是Spring提供的一个高级的IOC容器,与BeanFactory的区别是,BeanFactory提供了容器最基本的功能,而ApplicationContext除了提供基本IOC容器的功能外,还能为用户提供更丰富的功能:
支持信息源,可以实现国际化
访问资源
支持应用事件
ApplicationContext中提供的附加服务
可以认为ApplicationContext 是 BeanFactory的扩展,在使用时,我们往往是直接与ApplicationContext 打交道。
ApplicationContext的继承关系:
在BeanFactory中,从BeanFactory到HierarchicalBeanFactory,再到ConfigurableBeanFactory,是一个条主要的设计路径。 BeanFactory中定义了基本的IOC容器规范,在HierarchicalBeanFactory接口中增加了getparantBeanFactory()的接口功能,使BeanFactory具备了双亲IOC容器的管理功能,在ConfigurableBeanFactory主要定义了一些对BeanFactory的配置功能
在ApplicationContext中,从BeanFactory到ListableBeanFactory,再到ApplicationContext,再到常用的WebApplicationContext或者ConfigurableApplicationContext接口。在BeanFactory简单接口的基础上增加了对高级容器的特性支持。
BeanDefinition SpringIOC容器帮我们管理了各种bean对象及其相互依赖的关系,依赖关系是使用BeanDefinition来保存的:
Spring关于Bean的装配,有下面三种方式:
在XML中进行显示配置
在java中进行显示配置
隐式的bean发现机制和自动装配
Bean的解析非常的复杂,功能被分的很细,需要扩展的地方也很多,必须保证有足够的灵活性,下面看一下基于xml配置文件解析的继承体系:
IOC容器的初始化 IOC容器的初始化包括:BeanDefinition的Resouce定位,BeanDefinition的载入和注册 三个基本的过程。需要注意的是Spring把上面过程进行了分离,并使用了不同的模块来完成,定位使用了ResourceLoader,解析使用了BeanDefinitionReader等。这样设计的目的可以让用户对这三个过程进行裁剪和扩展,定义出适合自己的IOC容器初始化过程。
下面来看一下两种IOC容器的创建过程,BeanFactory以XmlBeanFactory为例,ApplicationContext 以 FileSystemXmlApplicationContext为例
XmlBeanFactroy XmlBeanFactory的源码定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class XmlBeanFactory extends DefaultListableBeanFactory { private final XmlBeanDefinitionReader reader; public XmlBeanFactory (Resource resource) throws BeansException { this (resource, (BeanFactory)null ); } public XmlBeanFactory (Resource resource, BeanFactory parentBeanFactory) throws BeansException { super (parentBeanFactory); this .reader = new XmlBeanDefinitionReader(this ); this .reader.loadBeanDefinitions(resource); } }
通过阅读XmlBeanFactory的源码可以看出,XmlBeanFactory继承自DefaultListableBeanFactory类。而DefaultListableBeanFactory类包含了基本IOC容器所具有的重要功能。那BeanDefinition的信息来源自哪,如何定位? 定位之后又如何读取解析呢?对于信息来源的定位封装成Spring中的Resource类来给出,解析是它的内部定义了一个XmlBeanDefinitionReader对象,有了这个对象,就有了处理xml文件的能力。参考XmlBeanFactory的实现,我们手动来模拟一下XmlBeanFactory的实现过程
1 2 3 4 5 6 7 8 ClassPathResource res = new ClassPathResource("beans.xml" ); DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory ); reader.loadBeanDefinitions(res);
通过上面的代码,总结一下IOC容器的使用步骤:
创建IOC抽象资源,这个抽象资源包含了BeanDefinition的定义信息
创建一个BeanFactory
创建一个BeanDefinition的读取器,通过一个回调配置给BeanFactory
从定义好的抽象资源中读取配置信息。完成载入和注册的定义后,IOC容器就建立了起来了。
FileSystemXmlApplicationContext 先来看一下FileSystemXmlApplicationContext的继承关系:
通过上面的继承关系,可以发现它的基类AbstractXmlApplicationContext中已经实现了主要的功能。
在看一下这个类的源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext { public FileSystemXmlApplicationContext (String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super (parent); this .setConfigLocations(configLocations); if (refresh) { this .refresh(); } } protected Resource getResourceByPath (String path) { if (path != null && path.startsWith("/" )) { path = path.substring(1 ); } return new FileSystemResource(path); } }
除了构造方法和getResourceByPath外,并没有其他的方法。也就说它只是实现了和它自身设计相关的两个功能。该类的调用方式:
1 ApplicationContext context =new FileSystemXmlApplicationContext(xmlPath);
上面调用了参数是字符串的构造函数,但是,对构造函数的调用最终都会转到下面的方法来执行,refresh方法启动了整个容器的初始化流程:
1 2 3 4 5 6 7 public FileSystemXmlApplicationContext (String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super (parent); this .setConfigLocations(configLocations); if (refresh) { this .refresh(); } }
可以发现,super(parent)这个方法最终是由其基类(AbstractApplicationContext)来执行,执行了AbstractApplicationContext的无参构造方法和setParent()方法。其代码如下,省略了静态代码块的定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public AbstractApplicationContext (ApplicationContext parent) { this (); setParent(parent); } public AbstractApplicationContext () { this .resourcePatternResolver = getResourcePatternResolver(); } protected ResourcePatternResolver getResourcePatternResolver () { return new PathMatchingResourcePatternResolver(this ); } public void setParent (ApplicationContext parent) { this .parent = parent; if (parent != null ) { Environment parentEnvironment = parent.getEnvironment(); if (parentEnvironment instanceof ConfigurableEnvironment) { getEnvironment().merge((ConfigurableEnvironment) parentEnvironment); } } }
调用父类的构造方法执行完成后,返回FileSystemXmlApplicationContext
类,执行setConfigLocations(configLocations)
方法,该方法的定义在类AbstractRefreshableConfigApplicationContext
中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public void setConfigLocations (String[] locations ) { if (locations != null ) { Assert.noNullElements(locations, "Config locations must not be null" ); this .configLocations = new String[locations.length]; for (int i = 0 ; i < locations.length; i++) { this .configLocations[i] = resolvePath(locations[i]).trim(); } } else { this .configLocations = null ; } }
在资源定位的时候,支持下面两种方式:
ClasspathResource res = new ClasspathResource(“a.xml,b.xml”);
ClasspathResource res = new ClasspathResource(“new String(){‘a.xml’ , ‘b.xml’}”) 具体实现的方式不在展开,感兴趣的可以去看一下源码实现
我们来看以上,程序执行到此处后,都做了哪些操作:
在AbstractApplicationContext中初始化了resourcePatternResolver(多资源文件的载入),用于获取Resource,关于何时使用后面再解释
将资源的定义路径保存在了configLocations数组中
到此,IOC容器根据资源定义路径获取Resouce的准备工作便完成了。
IOC容器的初始化过程 在开始分析初始化过程之前,先从宏观上对初始化的过程做一个简单的介绍,有一个大体框架的初始化模型,方便后面的理解,初始化过程分成了三个过程:
Resource定位
BeanDefinition的载入
向IOC容器注册这些BeanDefinition信息。这个过程是通过BeanDefinitionRegistry接口的实现来完成的。最终注入到HashMap中去,这个hashmap就是持有beandefinition数据的。
下面来看一下FileSystemXmlApplicationContext中的关于refresh()方法的调用,实际调用的是AbstractApplicationContext中的refresh()方法,该方法定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public void refresh () throws BeansException, IllegalStateException { synchronized (this .startupShutdownMonitor) { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); try { postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); initMessageSource(); initApplicationEventMulticaster(); onRefresh(); registerListeners(); finishBeanFactoryInitialization(beanFactory); finishRefresh(); }catch (BeansException ex) { destroyBeans(); cancelRefresh(ex); throw ex; } } }
refresh()
方法主要为IOC容器Bean的生命周期提供管理条件。Spring IOC容器的生成是从refreshBeanFactory()
方法开始的,也就是执行了下面的代码:
1 2 3 4 5 6 7 8 9 10 11 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); protected ConfigurableListableBeanFactory obtainFreshBeanFactory () { refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }
在AbstractApplicationContext抽象类中,只是进行了refreshBeanFactory()
方法的定义,方法的实现是在其子类AbstractRefreshableApplicationContext中实现的,在子类的定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 protected final void refreshBeanFactory () throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); synchronized (this .beanFactoryMonitor) { this .beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
上面代码loadBeanDefinitions(beanFactory);
我们说是一个委派模式,只是进行了方法的定义,具体实现则是由AbstractXmlApplicationContext
类实现,在该方法中创建了读取器XmlBeanDefinitionReader
的实例,然后把这个读取器在IOC容器中设置好,最后是启动读取器来完成对BeanDefinition
在IOC容器中的载入,定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Override protected void loadBeanDefinitions (DefaultListableBeanFactory beanFactory) throws BeansException, IOException { XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); beanDefinitionReader.setResourceLoader(this ); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this )); initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); }
在XmlBeanDefinitionReader
的初始化过程中,还进行了一些其他的操作,具体如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) { super (registry); } protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) { this .registry = registry; if (this .registry instanceof ResourceLoader) { this .resourceLoader = (ResourceLoader) this .registry; } else { this .resourceLoader = new PathMatchingResourcePatternResolver(); } if (this .registry instanceof EnvironmentCapable) { this .environment = ((EnvironmentCapable) this .registry).getEnvironment(); } else { this .environment = new StandardEnvironment(); } }
通过上面代码发现,在创建XmlBeanDefinitionReader的过程中,完成了resourceLoader和eviironment的赋值操作。
首先得到BeanDefinition信息的Resource定位,然后直接调用XmlBeanDefinitionReader来读取,具体的载入过程是委托给BeanDefinitionReader来完成的。因为使用的FileSystemXmlApplicationContext, getConfigResources()方法返回的是null,所以程序会走第二个分支
1 2 3 4 5 6 7 8 9 10 11 12 13 14 protected void loadBeanDefinitions (XmlBeanDefinitionReader reader) throws BeansException, IOException { Resource[] configResources = getConfigResources(); if (configResources != null ) { reader.loadBeanDefinitions(configResources); } String[] configLocations = getConfigLocations(); if (configLocations != null ) { reader.loadBeanDefinition(configLocations); } }
程序分析到这,来梳理一下上面的执行流程。
在FileSystemXmlApplicationContext一共做了三件事
调用了父类的构造器,进行了初始化
设置了BeanDefinition的定义路径
执行了Refresh()方法
refresh()方法来启动整个BeanDefinition的载入过程
创建容器 DefaultListableBeanFactory
创建了XmlXmlBeanDefinitionReader
开始准备通过reader来加载资源
AbstractBeanDefinitionReader读取Bean定义资源,AbstractBeanDefinitionReader的loadBeanDefinitions方法源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 public int loadBeanDefinitions (String... locations) throws BeanDefinitionStoreException { Assert.notNull(locations, "Location array must not be null" ); int counter = 0 ; String[] var3 = locations; int var4 = locations.length; for (int var5 = 0 ; var5 < var4; ++var5) { String location = var3[var5]; counter += this .loadBeanDefinitions(location); } return counter; } public int loadBeanDefinitions (String location) throws BeanDefinitionStoreException { return this .loadBeanDefinitions(location, (Set)null ); } public int loadBeanDefinitions (String location, Set<Resource> actualResources) throws BeanDefinitionStoreException { ResourceLoader resourceLoader = getResourceLoader(); if (resourceLoader == null ) { throw new BeanDefinitionStoreException("Cannot import bean definitions from location [" + location + "]: no ResourceLoader available" ); } if (resourceLoader instanceof ResourcePatternResolver) { try { Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location); int loadCount = loadBeanDefinitions(resources); if (actualResources != null ) { for (Resource resource : resources) { actualResources.add(resource); } } if (logger.isDebugEnabled()) { logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]" ); } return loadCount; } catch (IOException ex) { throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]" , ex); } } else { Resource resource = resourceLoader.getResource(location); int loadCount = loadBeanDefinitions(resource); if (actualResources != null ) { actualResources.add(resource); } if (logger.isDebugEnabled()) { logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]" ); } return loadCount; } } public int loadBeanDefinitions (Resource... resources) throws BeanDefinitionStoreException { Assert.notNull(resources, "Resource array must not be null" ); int counter = 0 ; Resource[] var3 = resources; int var4 = resources.length; for (int var5 = 0 ; var5 < var4; ++var5) { Resource resource = var3[var5]; counter += this .loadBeanDefinitions((Resource)resource); } return counter; }
上面的方法主要进行了两件事:
调用资源加载器获取资源 resourceLoader.getResource(location)
真正执行加载功能的是子类XmlBeanDefinitionReader的loadBeanDefinitions方法
loadBeanDefinitions()方法在AbstractBeanDefinitionReader中并没有具体的实现,它会转到XmlBeanDefinitionReader中的loadBeanDefinitions(Resource resource)中运行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 public int loadBeanDefinitions (Resource resource ) throws BeanDefinitionStoreException { return this .loadBeanDefinitions(new EncodedResource(resource)); } public int loadBeanDefinitions (EncodedResource encodedResource ) throws BeanDefinitionStoreException { Assert.notNull(encodedResource, "EncodedResource must not be null" ); if (this .logger.isInfoEnabled()) { this .logger.info("Loading XML bean definitions from " + encodedResource.getResource()); } Object currentResources = (Set)this .resourcesCurrentlyBeingLoaded.get (); if (currentResources == null ) { currentResources = new HashSet(4 ); this .resourcesCurrentlyBeingLoaded.set (currentResources); } if (!((Set)currentResources).add (encodedResource)) { throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!" ); } else { int var5; try { InputStream ex = encodedResource.getResource().getInputStream(); try { InputSource inputSource = new InputSource(ex); if (encodedResource.getEncoding() != null ) { inputSource.setEncoding(encodedResource.getEncoding()); } var5 = this .doLoadBeanDefinitions(inputSource, encodedResource.getResource()); } finally { ex.close(); } } catch (IOException var15) { throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), var15); } finally { ((Set)currentResources).remove (encodedResource); if (((Set)currentResources).isEmpty()) { this .resourcesCurrentlyBeingLoaded.remove (); } } return var5; } } protected int doLoadBeanDefinitions (InputSource inputSource, Resource resource )throws BeanDefinitionStoreException { try { Document doc = doLoadDocument(inputSource, resource); return registerBeanDefinitions(doc, resource); } catch (....) { throw ex; } }
将XML文件转换成Document对象,解析过程由documentLoader实现,getValidationModeForResource(resource)验证xml文件的模式 DTD还是XSD,此方法不在展开。
1 2 3 protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception { return this .documentLoader.loadDocument(inputSource,getEntityResolver(), this .errorHandler,getValidationModeForResource(resource),isNamespaceAware()); }
创建Document 的过程:
1 2 3 4 5 6 7 8 9 10 11 public Document loadDocument (InputSource inputSource, EntityResolver entityResolver,ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception { DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware); if (logger.isDebugEnabled()) { logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]" ); } DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler); return builder.parse(inputSource); }
spring并没有对XML进行特殊的处理,使用了SAX对xml文档进行解析,操作分为三步:
创建DocumentBuilderFactory
创建DocumentBuilder
解析inputSource对象,返回Document 对象
Document对象代表了一个XML文档的模型树,所有的其他Node都以一定的顺序包含在Document对象之内,排列成一个树状结构,以后对XML文档的所有操作都与解析器无关,直接在这个对象上操作即可。NodeList代表了包含一个或者多个Node的列表,操作上可以看作数组,使用getLength()获得列表中的节点数,item(int index ) 返回集合中第index个项。Node对象很少使用,会使用它的自对象Element,Attr 等。
至此,Spring IOC容器根据定位的Bean定义资源文件,并将其加载读入转换为document对象的过程完成。
上面略微呢有一点跑题,document对象的创建过程可能不是我们最关心的,我们关心就是Spring的BeanDefinition是怎样按照Spring的Bean语义要求进行解析并转化为容器内部数据结构的。 这个过程是在下面的方法中执行的,我们来看一下,具体的操作过程:
1 2 3 4 5 6 7 8 9 public int registerBeanDefinitions (Document doc, Resource resource) throws BeanDefinitionStoreException { BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); int countBefore = getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; }
Bean定义资源的解析分为以下两个过程:
通过调用xml解析器,将资源定义文件转换为Document对象,document对应并没有按照spring bean的规则进行解析。
在完成通用xml解析之后,按照Spring的Bean规则对Document对象进行解析,这个过程是在documentReader中实现的。具体的操作是由DefaultBeanDefinitionDocumentReader完成的。 处理的结果由BeanDefinitionHolder对象持有。解析过程由BeanDefinitionParserDelegate来实现。
来看下面的流程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 public void registerBeanDefinitions (Document doc, XmlReaderContext readerContext ) { this .readerContext = readerContext; logger.debug("Loading bean definitions" ); Element root = doc.getDocumentElement(); doRegisterBeanDefinitions(root); } protected void doRegisterBeanDefinitions (Element root ) { BeanDefinitionParserDelegate parent = this .delegate ; this .delegate = createDelegate(getReaderContext(), root, parent); if (this .delegate .isDefaultNamespace(root)) { String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { if (logger.isInfoEnabled()) { logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +"] not matching: " + getReaderContext().getResource()); } return ; } } } preProcessXml(root); parseBeanDefinitions(root, this .delegate ); postProcessXml(root); this .delegate = parent; } protected BeanDefinitionParserDelegate createDelegate (XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate ) { BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext); delegate .initDefaults(root, parentDelegate); return delegate ; }
解析document文件,不同的命名的空间采用不同的方法处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 protected void parseBeanDefinitions (Element root,BeanDefinitionParserDelegate delegate ) { if (delegate .isDefaultNamespace(root)) { NodeList nl = root.getChildNodes(); for (int i = 0 ; i < nl.getLength(); i++) { Node node = nl.item(i); if (node instanceof Element) { Element ele = (Element) node; if (delegate .isDefaultNamespace(ele)) { parseDefaultElement(ele, delegate ); } else { delegate .parseCustomElement(ele); } } } } else { delegate .parseCustomElement(root); } }
使用spring的Bean规则解析Document元素节点,有些元素节点是 等,则分别进行解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 private void parseDefaultElement (Element ele, BeanDefinitionParserDelegate delegate ) { if (delegate .nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele); } else if (delegate .nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele); } else if (delegate .nodeNameEquals(ele, BEAN_ELEMENT)) { processBeanDefinition(ele, delegate ); } else if (delegate .nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { doRegisterBeanDefinitions(ele); } }
主要看一下对bean标签的解析过程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 protected void processBeanDefinition (Element ele,BeanDefinitionParserDelegate delegate ) { BeanDefinitionHolder bdHolder = delegate .parseBeanDefinitionElement(ele); if (bdHolder != null ) { bdHolder = delegate .decorateBeanDefinitionIfRequired(ele, bdHolder); try { BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { .... } getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }
下面看一下parseBeanDefinitionElement()方法的具体实现,对于BeanDefinition的注册时存放在ConcurrentHashMap中的,beanName变为存放的健:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { String id = ele.getAttribute(ID_ATTRIBUTE); String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); List <String > aliases = new ArrayList<String >(); if (StringUtils.hasLength(nameAttr)) { String [] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); } String beanName = id; if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { beanName = aliases.remove(0 ); if (logger.isDebugEnabled()) { logger.debug("...." ); } } if (containingBean == null ) { checkNameUniqueness(beanName, aliases, ele); } AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null ) { if (!StringUtils.hasText(beanName)) { try { if (containingBean != null ) { beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this .readerContext.getRegistry(), true ); } else { beanName = this .readerContext.generateBeanName(beanDefinition); String beanClassName = beanDefinition.getBeanClassName(); if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&!this .readerContext.getRegistry().isBeanNameInUse(beanClassName)) { aliases.add(beanClassName); } } if (logger.isDebugEnabled()) { logger.debug("...." ); } } catch (Exception ex) { error(ex.getMessage(), ele); return null ; } } String [] aliasesArray = StringUtils.toStringArray(aliases); return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null ; }
BeanDefinition可以看成是对定义的抽象,这个数据对象中封装的数据大多都是与定义相关的,也有很多就是我们在定义Bean时看到的那些Spring标记。这个BeanDefinition数据类型是非常重要的,它封装了很多基本数据,这些都是Ioc容器需要的,上面代码最后我们返回了一个BeanDefinitionHolder实例,这个实例封装了beanDefinition,beanName, aliase三个信息,beanDefinition中也包含了beanName,aliase信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) { this .parseState.push(new BeanEntry(beanName)); String className = null ; if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } try { String parent = null ; if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } AbstractBeanDefinition bd = createBeanDefinition(className, parent); parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); parseMetaElements(ele, bd); parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); parseConstructorArgElements(ele, bd); parsePropertyElements(ele, bd); parseQualifierElements(ele, bd); bd.setResource(this .readerContext.getResource()); bd.setSource(extractSource(ele)); return bd; } catch (ClassNotFoundException ex) { ... } catch (NoClassDefFoundError err) { ... } catch (Throwable ex) { ... } finally { this .parseState.pop(); } return null ; }
从上面的代码可以看出,要解析属性首先要创建用于承载属性的实例,也就是创建GenericBeanDefinition类型的实例,而代码createBeanDefinition(className,parent)的作用就是实现此功能。创建完承接的实例后,便可以进行各种属性的解析了,首先进行解析的是在 标签中定义的各种属性,如scope, singleton,abstract,lazy-init等,然后再解析子标签中的属性,如:lookup-method ,constructor-arg等。解析完成之后关联到实例上,之所以能进行关联,是因为xml中所有的配置都能在GenericBeanDefinition的实力类中找到对应的配置。 此时容器还没有起作用,要想起作用,需要向容器进行注册。
分析到这,已经完成了xml文件向BeanDefinition的转化,每个一个标签都会转化成一个BeanDefinition对应的实体。实体中包含了中定义的所有属性。
BeanDefinition在IOC容器中的注册 前面只是进行了BeanDefinition在IOC容器中的载入和解析过程,这些动作完成后,已经完成了定义的数据转化为BeanDefinition的过程。下面代码继续执行,看一下注册的过程,也就是processBeanDefinition函数中的BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder,getReaderContext().getRegistry())的代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public static void registerBeanDefinition (BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry )throws BeanDefinitionStoreException { String beanName = definitionHolder.getBeanName(); registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); String[] aliases = definitionHolder.getAliases(); if (aliases != null ) { for (String alias : aliases) { registry.registerAlias(beanName, alias ); } } }
最终承接注册任务方法是在DefaultListableBeanFactory类中定义的,为了更好的排版,我对下面的代码进行了删减,主要删除了抛出异常信息和日志信息,并不影响代码的逻辑,对于beanDefinition的注册,做了一些验证之后,直接将beanDefinition放入了Map中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException { if (beanDefinition instanceof AbstractBeanDefinition) { try { ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { .... } } BeanDefinition oldBeanDefinition; oldBeanDefinition = this .beanDefinitionMap.get (beanName); if (oldBeanDefinition != null ) { if (!isAllowBeanDefinitionOverriding()) { throw ... } else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) { if (this .logger.isWarnEnabled()) { this .logger.warn("...." ); } } else if (!beanDefinition.equals(oldBeanDefinition)) { if (this .logger.isInfoEnabled()) { this .logger.info("...." ); } } else { if (this .logger.isDebugEnabled()) { this .logger.debug("..." ); } } this .beanDefinitionMap.put(beanName, beanDefinition); } else { if (hasBeanCreationStarted()) { synchronized (this .beanDefinitionMap) { this .beanDefinitionMap.put(beanName, beanDefinition); List<String> updatedDefinitions = new ArrayList<String>(this .beanDefinitionNames.size() + 1 ); updatedDefinitions.addAll(this .beanDefinitionNames); updatedDefinitions.add(beanName); this .beanDefinitionNames = updatedDefinitions; if (this .manualSingletonNames.contains(beanName)) { Set<String> updatedSingletons = new LinkedHashSet<String>(this .manualSingletonNames); updatedSingletons.remove(beanName); this .manualSingletonNames = updatedSingletons; } } } else { this .beanDefinitionMap.put(beanName, beanDefinition); this .beanDefinitionNames.add(beanName); this .manualSingletonNames.remove(beanName); } this .frozenBeanDefinitionNames = null ; } if (oldBeanDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } }
至此,Bean定义资源文件中配置的Bean被解析过后,已经注册到IoC容器中,被容器管理起来,真正完成了IoC容器初始化所做的全部工作。现 在IoC容器中已经建立了整个Bean的配置信息,这些BeanDefinition信息已经可以使用,并且可以被检索,IoC容器的作用就是对这些注册的Bean定义信息进行处理和维护。这些的注册的Bean定义信息是IoC容器控制反转的基础,正是有了这些注册的数据,容器才可以进行依赖注入。
依赖注入 执行完上面的操作后,IOC容器已经实现了对Bean管理定义的相关数据,但是此时IOC容器还没有对所管理的Bean进行依赖注入,依赖注入在以下两种情况下发生:
用户第一次通过getBean()方法想容器索取时,进行依赖注入
当用户在Bean的定义中为配置了lazy-init属性,让容器在解析注册时进行欲初始化,触发依赖注入
AbstactBeanFactory 通过getBean()函数获取被管理的Bean,但是因为lazyinit默认为false,所以spring会进行部分实例的初始化操作,让我们回退到AbstactApplicationContext类的finishBeanFactoryInitialization(beanFactory)方法,该方法进行了所有单例类的初始化操作,初始化的动作包装在了getBean()方法中,这个方法是获取Bean的地方,也是依赖注入发生的地方,对genBean的调用会转入到doGetBean()方法来执行,来看一下该方法的定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object [] args, boolean typeCheckOnly)throws BeansException { final String beanName = transformedBeanName(name); Object bean; Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null ) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("..." ); } else { logger.debug("..." ); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null ); } else { if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { String nameToLookup = originalBeanName(name); if (args != null ) { return (T) parentBeanFactory.getBean(nameToLookup, args); } else { return parentBeanFactory.getBean(nameToLookup, requiredType); } } if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); String [] dependsOn = mbd.getDependsOn(); if (dependsOn != null ) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(。。。); } registerDependentBean(dep, beanName); getBean(dep); } } if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object >() { @Override public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { Object prototypeInstance = null ; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { String scopeName = mbd.getScope(); final Scope scope = this .scopes.get (scopeName); if (scope == null ) { throw new IllegalStateException("..." ); } try { Object scopedInstance = scope.get (beanName, new ObjectFactory<Object >() { @Override public Object getObject() throws BeansException { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } } }); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new BeanCreationException(...); } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) { try { return getTypeConverter().convertIfNecessary(bean, requiredType); } catch (TypeMismatchException ex) { if (logger.isDebugEnabled()) { logger.debug(....); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }
OK,上面的流程走完了,接下来该分析分支方法了, 没错,就是那个方法crateBean(),其定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; //确保BeanDefinition中的class被加载 Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } //准备方法覆写,涉及到一个概念:MethodOverrides,来自于Bean定义的<lookup-method>和<replaced-method>。感兴趣的自行研究 try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { //让BeanPostProcessors 有机会返回一个代理实例而不是bean实例 //要彻底了解清楚这个,需要看InstantiationAwwareBeanPostProcessor接口 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } //核心方法,创建bean Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; }
继续来看 doCreateBean()方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object [] args)throws BeanCreationException { BeanWrapper instanceWrapper = null ; if (mbd.isSingleton()) { instanceWrapper = this .factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null ) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null ); Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null ): mbd.resolvedTargetType = beanType; synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed" , ex); } mbd.postProcessed = true ; } } boolean earlySingletonExposure = (mbd.isSingleton() && this .allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references" ); } addSingletonFactory(beanName, new ObjectFactory<Object >() { @Override public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } }); } Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null ) { exposedObject = initializeBean(beanName, exposedObject, mbd); } } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed" , ex); } } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false ); if (earlySingletonReference != null ) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this .allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String [] dependentBeans = getDependentBeans(beanName); Set <String > actualDependentBeans = new LinkedHashSet<String >(dependentBeans.length); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(。。。); } } } } try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException(。。。); } return exposedObject; }
到此,doCreateBean方法便执行完了,上面的方法主要执行了三个步骤:
创建Bean实例createBeanInstance方法
依赖注入populateBean方法
回调方法initializeBean
下面介绍与依赖注入关系特别密切的方法createBeanInstance和populateBean方法。这个方法的主要作用就是实例化我们指定的类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 protected BeanWrapper createBeanInstance (String beanName, RootBeanDefinition mbd, Object[] args) { Class<?> beanClass = resolveBeanClass(mbd, beanName); if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(....); } if (mbd.getFactoryMethodName() != null ) { return instantiateUsingFactoryMethod(beanName, mbd, args); } boolean resolved = false ; boolean autowireNecessary = false ; if (args == null ) { synchronized (mbd.constructorArgumentLock) { if (mbd.resolvedConstructorOrFactoryMethod != null ) { resolved = true ; autowireNecessary = mbd.constructorArgumentsResolved; } } } if (resolved) { if (autowireNecessary) { return autowireConstructor(beanName, mbd, null , null ); } else { return instantiateBean(beanName, mbd); } } Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } return instantiateBean(beanName, mbd); }
在创建实例时,重要的是下面代码:
1 beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent );
继续跟进一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public Object instantiate (RootBeanDefinition bd, String beanName, BeanFactory owner) { if (bd.getMethodOverrides().isEmpty()) { Constructor<?> constructorToUse; synchronized (bd.constructorArgumentLock) { constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod; if (constructorToUse == null ) { final Class<?> clazz = bd.getBeanClass(); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface" ); } try { if (System.getSecurityManager() != null ) { constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() { @Override public Constructor<?> run() throws Exception { return clazz.getDeclaredConstructor((Class[]) null ); } }); } else { constructorToUse = clazz.getDeclaredConstructor((Class[]) null ); } bd.resolvedConstructorOrFactoryMethod = constructorToUse; } catch (Throwable ex) { throw new BeanInstantiationException(clazz, "No default constructor found" , ex); } } } return BeanUtils.instantiateClass(constructorToUse); } else { return instantiateWithMethodInjection(bd, beanName, owner); } }
判断一下是否存在方法覆写,如果不存在就使用java反射的方式创建实例,否则使用CGLIB来创建实例。
在这简单说一下,spring创建Bean的两种方式,一种是通过BeanUtis(JVM的反射功能,必须要基于接口才能实现),另一种就是CGLIB来生成。具体的不做深入分析,会放入AOP中来说明。到这实例的创建就完成了, 下面说一下属性的注入.
bean 属性注入,上面的代码已经完成了Bean对象的实例化,实例化对象已经生成,怎样把这些Bean对象的依赖关系处理好,依赖关系已经保存在了BeanDefinition中,看下面的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 protected void populateBean (String beanName, RootBeanDefinition mbd, BeanWrapper bw) { PropertyValues pvs = mbd.getPropertyValues(); if (bw == null ) { if (!pvs.isEmpty()) { throw new BeanCreationException(。。。); } else { return ; } } boolean continueWithPropertyPopulation = true ; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false ; break ; } } } } if (!continueWithPropertyPopulation) { return ; } if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null ) { return ; } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); } } applyPropertyValues(beanName, mbd, bw, pvs); }
initializeBean属性注入完成后,这一步其实就是处理各种回调了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null ) { AccessController.doPrivileged(new PrivilegedAction<Object >() { @Override public Object run() { invokeAwareMethods(beanName, bean); return null ; } }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null ), beanName, "Invocation of init method failed" , ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
转载自-简书