Spring源码分析(1)-IoC容器的实现
最近在看《Spring技术内幕》这本书学习Spring的技术源码,写博客来记录自己的学习过程。
第一章
这一章主要介绍了Spring的子项目和核心实现、Spring出现的目标。
第二章-IoC容器的实现
控制反转
主动获取依赖的过程:Test对象需要用到Hello属性对象的时候,自己创建一个Hello对象。
public class Hello{ public void sayHello(){ System.out.println("hello"); } } public class Test{ Hello hello = new Hello(); public void test(){ hello.sayHello(); } }
但是控制反转的是Spring框架已经把这个Hello对象创建好了,保存在框架里面,当Test需要用到Hello对象的时候,Test对象只需要向Spring框架说我要Hello对象,Spring就会给他一个Hello对象,这个过程就是依赖注入。
Spring IoC容器的设计
而Spring提供的最基本的BeanFactory的实现类是DefaultListableBeanFactory,这个类是也是实现ApplicationContext接口的一些高级容器的基础容器。以XmlBeanFactory实现类为例的编程式IoC容器,这个就是XML配置形式的IoC容器的初始化过程。
//获取定义了bean信息的xml配置文件位置 ClassPathResource res = new ClassPathResource("bean.xml"); //创建一个BeanFactory DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); //创建一个BeanDefinition的读取器,并设置把读取到的信息加载到BeanFactory XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory); //实现xml配置文件的信息读取,加载和注册BeanDefinition整个过程 reader.loadBeanDefinition(res);
IoC容器的初始化过程-Resource定位过程
这个定位过程实际上就是
ClassPathResource res = new ClassPathResource("bean.xml");
以FileSystemXmlApplicationContext为例,写一个Debug过程:
在容器初始化的时候会调用FileSystemXmlApplicationContext的构造方法,
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { //指定自己的双亲IoC容器 super(parent); //指定包含BeanDefinition信息的配置文件所在路径 setConfigLocations(configLocations); //刷新容器,实现创建容器、载入、实例化对象的过程 if (refresh) { refresh(); } }
接着进入上面代码的refresh()方法
- AbstractApplicationContext.refresh()
- AbstractApplicationContext.obtainFreshBeanFactory()
- AbstractRefreshableApplicationContext.refreshBeanFactory()
//AbstractRefreshableApplicationContext.refreshBeanFactory() protected final void refreshBeanFactory() throws BeansException { //如果存在BeanFactory,关闭并销毁 if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { //创建一个DefaultListableBeanFactory的BeanFactory,并初始化 DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); //载入BeanDefinition的信息,在本类提供了这个方法的抽象 //在AbstractXmlApplicationContext子类重写了,实际是调用了子类的这个方法 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)继续Debug
- AbstractXmlApplicationContext.loadBeanDefinitions()
- AbstractBeanDefinitionReader.loadBeanDefinitions(String… locations)
//同是在AbstractBeanDefinitionReader里面的 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) { // 调用DefaultResourceLoader的getResource完成具体的Resource定位 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 { // 根据URL实现单个资源文件的定位 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; } }
- PathMatchingResourcePatternResolver.getResources()
- DefaultResourceLoader.getResource()
接下来步入进去看一下的实现
public Resource getResource(String location) { Assert.notNull(location, "Location must not be null"); //处理带有classpath的Resource for (ProtocolResolver protocolResolver : this.protocolResolvers) { Resource resource = protocolResolver.resolve(location, this); if (resource != null) { return resource; } } if (location.startsWith("/")) { return getResourceByPath(location); } else if (location.startsWith(CLASSPATH_URL_PREFIX)) { return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader()); } else { try { // 处理带有URL表示的Resource URL url = new URL(location); return new UrlResource(url); } catch (MalformedURLException ex) { //处理既不是classpath,也不是URL标识的资源,调用接口的getResourceByPath(location)方法,通常在子类实现 //此时此方法在FileSystemXmlApplicationContext.getResourceByPath(location)实现了 return getResourceByPath(location); } } }
- FileSystemXmlApplicationContext.getResourceByPath(location)
protected Resource getResourceByPath(String path) { if (path != null && path.startsWith("/")) { path = path.substring(1); } return new FileSystemResource(path); }
最终返回一个实现了Resource接口的实例,完成了Resource资源的定位,接下来就是BeanDefinition的载入了。
BeanDefinition的载入和解析
继续从FileSystemXmlApplicationContext的构造器开始
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException
- AbstractApplicationContext.refresh()
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { prepareRefresh(); //这里是在子类中启动refreshBeanFactory的地方 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); /*省略下部的代码,主要研究obtainFreshBeanFactory()*/ } }
- AbstractApplicationContext.obtainFreshBeanFactory()
- AbstractRefreshableApplicationContext.refreshBeanFactory()
protected final void refreshBeanFactory() throws BeansException { //如果存在BeanFactory,关闭并销毁 if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { //创建一个DefaultListableBeanFactory的BeanFactory,并初始化 DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); //载入BeanDefinition的信息,在本类提供了这个方法的抽象 //在AbstractXmlApplicationContext子类重写了,实际是调用了子类的这个方法 /*启动对BeanDefinition的载入*/< 20000 /span> loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
- AbstractXmlApplicationContext.loadBeanDefinitions()
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { //创建一个XmlBeanDefinitionReader并设置把读取到的信息设置在beanFactory XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // 配置XmlBeanDefinitionReader的读取环境和资源加载器 beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); /*启动Bean定义信息载入的过程*/ initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); } protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { //以Resource形式获取配置文件位置 Resource[] configResources = getConfigResources(); if (configResources != null) { reader.loadBeanDefinitions(configResources); } //以String形式获取配置文件位置 String[] configLocations = getConfigLocations(); if (configLocations != null) { /*接着进入这里分析*/ reader.loadBeanDefinitions(configLocations); } } protected Resource[] getConfigResources() { return null; }
-AbstractBeanDefinitionReader.loadBeanDefinitions()
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); /*前面是定位,此处是加载BeanDefinition*/ int loadCount = loadBeanDefinitions(resources); /*省略此处代码*/ } catch (IOException ex) { /*省略此处代码*/ } } else { /*省略此处代码*/ } return loadCount; } } public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException { //如果Resource为空则返回 //遍历所有Resource再载入BeanDefinition Assert.notNull(resources, "Resource array must not be null"); int counter = 0; for (Resource resource : resources) { counter += loadBeanDefinitions(resource); } return counter; }
- XmlBeanDefinitionReader.loadBeanDefinitions()
//调用入口 public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException { return loadBeanDefinitions(new EncodedResource(resource)); } //载入XML形式的BeanDefinition的地方 public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { Assert.notNull(encodedResource, "EncodedResource must not be null"); if (logger.isInfoEnabled()) { logger.info("Loading XML bean definitions from " + encodedResource.getResource()); } Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get(); if (currentResources == null) { currentResources = new HashSet<EncodedResource>(4); this.resourcesCurrentlyBeingLoaded.set(currentResources); } if (!currentResources.add(encodedResource)) { throw new BeanDefinitionStoreException( "Detected cyclic loading of " + encodedResource + " - check your import definitions!"); } //这里得到XML文件,并得到InputSource准备进行读取 try { InputStream inputStream = encodedResource.getResource().getInputStream(); try { InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } /*这里是真正读取BeanDefinition的入口,从这里进去看看具体实现*/ return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); } finally { inputStream.close(); } } catch (IOException ex) { throw new BeanDefinitionStoreException( "IOException parsing XML document from " + encodedResource.getResource(), ex); } finally { currentResources.remove(encodedResource); if (currentResources.isEmpty()) { this.resourcesCurrentlyBeingLoaded.remove(); } } }
- XmlBeanDefinitionReader.doLoadBeanDefinitions()
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { //获取XML文件的Document对象 Document doc = doLoadDocument(inputSource, resource); /*启动对BeanDefinition的载入过程,从这里进去*/ return registerBeanDefinitions(doc, resource); } /*省略异常代码*/ }
- XmlBeanDefinitionReader.registerBeanDefinitions()
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { //创建BeanDefinitionDocumentReader对XML的BeanDefinition进行解析, BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); int countBefore = getRegistry().getBeanDefinitionCount(); /*具体的解析过程从这里进去*/ documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; } public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; logger.debug("Loading bean definitions"); Element root = doc.getDocumentElement(); doRegisterBeanDefinitions(root); }
- DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions()
- DefaultBeanDefinitionDocumentReader.parseBeanDefinitions()
- DefaultBeanDefinitionDocumentReader.parseDefaultElement()
- DefaultBeanDefinitionDocumentReader.processBeanDefinition()
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { /*解析BeanDefinition并用BeanDefinitionHolder封装BeanDefinition、beanName等信息,我们要研究载入过程,从这里进去*/ BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // 向容器注册BeanDefinition BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } // 注册完成后发送消息 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }
- BeanDefinitionParserDelegate.parseBeanDefinitionElement()
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) { return parseBeanDefinitionElement(ele, null); } public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { /*省略代码,这部分主要取得再<bean>元素中定义的id、name和aliase等属性*/ if (containingBean == null) { checkNameUniqueness(beanName, aliases, ele); } /*这个方法会引发对Bean元素的详细解析,从这里进去研究*/ AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); /*省略后面的代码*/ } public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, BeanDefinition containingBean) { this.parseState.push(new BeanEntry(beanName)); //这里读取<bean>中定义的信息,载入到BeanDefinition中,不涉及实例化的过程 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); } //新建BeanDefinition对象,为Bean定义信息的载入做准备 AbstractBeanDefinition bd = createBeanDefinition(className, parent); //对当前Bean的元素属性进行解析,设置Description信息 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); //对各种<bean>元素进行解析 parseMetaElements(ele, bd); parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); //解析<bean>构造函数设置 parseConstructorArgElements(ele, bd); //解析<bean>的property设置 parsePropertyElements(ele, bd); parseQualifierElements(ele, bd); bd.setResource(this.readerContext.getResource()); bd.setSource(extractSource(ele)); return bd; } /*省略异常代码*/ finally { this.parseState.pop(); } return null; }
这个就是解析BeanDefinition的具体过程,具体的property参数或者是Constructor参数解析可以深入研究parseConstructorArgElements(ele, bd)和parsePropertyElements(ele, bd)。
BeanDefinition在IoC容器中的注册
在DefaultListableBeanFactory类中使用一个Map集合保存beanName->BeanDefinition
/** Map of bean definition objects, keyed by bean name */ private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
从DefaultBeanDefinitionDocumentReader.processBeanDefinition()继续研究
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { /*注册BeanDefinition到IoC容器,我们从这里开始*/ BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } // Send registration event. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }
- BeanDefinitionReaderUtils.registerBeanDefinition()
- DefaultListableBeanFactory.registerBeanDefinition()
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); } } //检查是否有相同名字的BeanDefinition已经在容器中注册 //如果有并且不能覆盖,则抛出异常 BeanDefinition oldBeanDefinition; oldBeanDefinition = this.beanDefinitionMap.get(beanName); if (oldBeanDefinition != null) { if (!isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound."); } else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) { // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE if (this.logger.isWarnEnabled()) { this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } else if (!beanDefinition.equals(oldBeanDefinition)) { if (this.logger.isInfoEnabled()) { this.logger.info("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } else { if (this.logger.isDebugEnabled()) { this.logger.debug("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } this.beanDefinitionMap.put(beanName, beanDefinition); } else { if (hasBeanCreationStarted()) { //如果是这个已经初始化结束,后来向容器中追加 //那么注册过程需要synchronized,保证数据的一致性 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 { // 如果容器继续处于启动阶段,那么就可以直接注册 /*这是正常注册BeanDefinition的过程,把Bean的名字存入到BeanDefinitionNames同时把beanName作为Map的Key, 把beanDefinition作为value存入到IoC容器持有的beanDefinitionMap中去*/ this.beanDefinitionMap.put(beanName, beanDefinition); this.beanDefinitionNames.add(beanName); this.manualSingletonNames.remove(beanName); } this.frozenBeanDefinitionNames = null; } if (oldBeanDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } }
至此,完成了Resource的定位,BeanDefinition的载入和注册。
阅读更多- Spring源码分析----IoC容器其他特性的设计与实现
- Spring源码分析(2)-IoC容器的实现
- Spring源码分析----IOC容器的实现(IoC容器的初始化过程(定位、载入解析、注册))
- Spring源码分析(二)-Spring IoC容器的初始化No.1
- 【Spring源码--IOC容器的实现】(二)BeanDefinition的Resource定位
- Spring IOC 容器源码分析 - 余下的初始化工作
- Spring IOC 容器源码分析 - 获取单例 bean
- 【Spring源码--IOC容器的实现】(一)Web容器的启动
- Spring核心IOC容器实现分析
- Spring源码分析(二)-Spring IoC容器的初始化No.2
- 对Spring IoC容器实现的结构分析
- Spring源码解析-IOC容器的实现-ApplicationContext
- Spring源码分析——Ioc实现原理
- Spring IOC 容器源码分析
- 【Spring源码--IOC容器的实现】-- 综述
- struts2源码分析-IOC容器的实现机制(上篇)
- 【Spring源码--IOC容器的实现】(四)BeanDefinition的注册
- 【Spring源码--IOC容器的实现】(六)Bean的依赖注入
- 一 spring源码分析--- IOC容器
- Spring源码分析--Ioc容器定位解析资源文件并注册BeanDefinition