Spring IOC 容器源码阅读笔记
来源:互联网 发布:少儿编程是什么意思 编辑:程序博客网 时间:2024/06/08 11:28
参考的文章
- Spring IOC容器源代码解析,作者带着看了一遍源码,边看边讲,非常nice。
正文
- 我对于Spring IOC(控制反转)的理解,是将对象的管理(控制)权从以前的程序员手中“反转”到了Spring IOC容器手中。
- Spring IOC容器的定义接口(最基本的IOC容器):BeanFactory,这个借口为具体的IOC容器的实现做了最基本的功能规定。
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; <T> T getBean(Class<T> 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, ResolvableType var2) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException; Class<?> getType(String var1) throws NoSuchBeanDefinitionException; String[] getAliases(String var1);}
- 围绕着BeanFactory,pring对于IOC容器有许多种实现(XmlBeanFactory,XmlWebApplicationContext.java,ClassPathXmlApplicationContext.java FileSystemXmlApplicationContext.java)。
- 我是以ClassPathXmlApplicationContext.java为例去看的源码。
ClassPathXmlApplicationContext构造器代码
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super(parent); this.setConfigLocations(configLocations); if(refresh) { this.refresh(); } }
- 主要是调用了refresh()方法。bean的初始化逻辑是在这里完成的。
refresh()方法(refresh方法是在AbstractApplicationContext里的)
public void refresh() throws BeansException, IllegalStateException { Object var1 = this.startupShutdownMonitor; synchronized(this.startupShutdownMonitor) { this.prepareRefresh(); ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); this.prepareBeanFactory(beanFactory); try { this.postProcessBeanFactory(beanFactory); this.invokeBeanFactoryPostProcessors(beanFactory); this.registerBeanPostProcessors(beanFactory); this.initMessageSource(); this.initApplicationEventMulticaster(); this.onRefresh(); this.registerListeners(); this.finishBeanFactoryInitialization(beanFactory); this.finishRefresh(); } catch (BeansException var9) { if(this.logger.isWarnEnabled()) { this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9); } this.destroyBeans(); this.cancelRefresh(var9); throw var9; } finally { this.resetCommonCaches(); } } }
- 这里重要的是
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
,获取一个新的beanFactory
obtainFreshBeanFactory()
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { this.refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = this.getBeanFactory(); if(this.logger.isDebugEnabled()) { this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory); } return beanFactory; }
this.refreshBeanFactory();
刷新beanFactory,如果已经建立了那么应该销毁重建。该方法是一个abstract方法,通过调试发现调用的是AbstractRefreshableApplicationContext
中实现的refreshBeanFactory方法
refreshBeanFactory()
protected final void refreshBeanFactory() throws BeansException { if(this.hasBeanFactory()) { this.destroyBeans(); this.closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = this.createBeanFactory(); beanFactory.setSerializationId(this.getId()); this.customizeBeanFactory(beanFactory); this.loadBeanDefinitions(beanFactory); Object var2 = this.beanFactoryMonitor; synchronized(this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException var5) { throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5); } }
- 实现了如果已经建立了beanFactory,那么就销毁并关闭,重新建立。这里的
this.loadBeanDefinitions(beanFactory);
需要讲一下,它去加载那些bean的定义。 - 在AbstractXmlApplicationContext中定义了对资源的读取过程,默认由XmlBeanDefinitionReader来读取:
loadBeanDefinitions()
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { Resource[] configResources = this.getConfigResources(); if(configResources != null) { reader.loadBeanDefinitions(configResources); } String[] configLocations = this.getConfigLocations(); if(configLocations != null) { reader.loadBeanDefinitions(configLocations); } }
doLoadBeanDefinitions()
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { Document doc = this.doLoadDocument(inputSource, resource); return this.registerBeanDefinitions(doc, resource);...}
registerBeanDefinitions()
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader(); int countBefore = this.getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource)); return this.getRegistry().getBeanDefinitionCount() - countBefore; }
- 主要作用的还是documentReader.registerBeanDefinitions()方法。经过调试,发现调用的是DefaultBeanDefinitionDocumentReader中的registerBeanDefinitions()。
- 又经过调试发现是documentReader.registerBeanDefinitions()中的doRegisterBeanDefinitions()。实现的。
doRegisterBeanDefinitions
protected void doRegisterBeanDefinitions(Element root) { BeanDefinitionParserDelegate parent = this.delegate; this.delegate = this.createDelegate(this.getReaderContext(), root, parent); if(this.delegate.isDefaultNamespace(root)) { String profileSpec = root.getAttribute("profile"); if(StringUtils.hasText(profileSpec)) { String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; "); if(!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { if(this.logger.isInfoEnabled()) { this.logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + this.getReaderContext().getResource()); } return; } } } this.preProcessXml(root); this.parseBeanDefinitions(root, this.delegate); this.postProcessXml(root); this.delegate = parent; }
实际上的解析工作都是交给delegate代理完成的。
parseBeanDefinitions()
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)) { this.parseDefaultElement(ele, delegate); } else { delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }
- 该方法是遍历所有的子节点,然后分为默认的命名空间(import,alias,bean,beans)和自定义的命名空间(dubbo,shiro等等)。
parseDefaultElement()
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { if(delegate.nodeNameEquals(ele, "import")) { this.importBeanDefinitionResource(ele); } else if(delegate.nodeNameEquals(ele, "alias")) { this.processAliasRegistration(ele); } else if(delegate.nodeNameEquals(ele, "bean")) { this.processBeanDefinition(ele, delegate); } else if(delegate.nodeNameEquals(ele, "beans")) { this.doRegisterBeanDefinitions(ele); } }
- 根据不同的nodeName做不同处理。
processBeanDefinition
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if(bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException var5) { this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5); } this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }
- 这里执行了delegate.parseBeanDefinitionElement()完成了对bean定义的解析,返回的BeanDefinitionHolder交给BeanDefinitionReaderUtils.registerBeanDefinition(),完成对一个bean的定义。
先说parseBeanDefinitionElement()
parseBeanDefinitionElement()
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { String id = ele.getAttribute("id"); String nameAttr = ele.getAttribute("name"); List<String> aliases = new ArrayList(); if(StringUtils.hasLength(nameAttr)) { String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; "); aliases.addAll(Arrays.asList(nameArr)); } String beanName = id; if(!StringUtils.hasText(id) && !aliases.isEmpty()) { beanName = (String)aliases.remove(0); if(this.logger.isDebugEnabled()) { this.logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases"); } } if(containingBean == null) { this.checkNameUniqueness(beanName, aliases, ele); } AbstractBeanDefinition beanDefinition = this.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(this.logger.isDebugEnabled()) { this.logger.debug("Neither XML 'id' nor 'name' specified - using generated bean name [" + beanName + "]"); } } catch (Exception var9) { this.error(var9.getMessage(), ele); return null; } } String[] aliasesArray = StringUtils.toStringArray(aliases); return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } else { return null; } }
- parseBeanDefinitionElement()方法具体完成。
parseBeanDefinitionElement()
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) { this.parseState.push(new BeanEntry(beanName)); String className = null; if(ele.hasAttribute("class")) { className = ele.getAttribute("class").trim(); } try { String parent = null; if(ele.hasAttribute("parent")) { parent = ele.getAttribute("parent"); } //创建一个AbstractBeanDefinition并设置好'类名'和'parent' AbstractBeanDefinition bd = this.createBeanDefinition(className, parent); //解析了Element的属性并设置到beanDefinition中去 this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description")); //设置启动参数 this.parseMetaElements(ele, bd); //设置被期望重写 this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); //设置被替换的方法 this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); this.parseConstructorArgElements(ele, bd); this.parsePropertyElements(ele, bd); this.parseQualifierElements(ele, bd); bd.setResource(this.readerContext.getResource()); bd.setSource(this.extractSource(ele)); //这里,是为了防止并发问题?????Spring在后面还用到了类似的手法 AbstractBeanDefinition var7 = bd; return var7; } catch (ClassNotFoundException var13) { this.error("Bean class [" + className + "] not found", ele, var13); } catch (NoClassDefFoundError var14) { this.error("Class that bean class [" + className + "] depends on not found", ele, var14); } catch (Throwable var15) { this.error("Unexpected failure during bean definition parsing", ele, var15); } finally { this.parseState.pop(); } return null; }
经过parseBeanDefinitionElement完成了beanDefinition的各种设置,再说registerBeanDefinition,把设置完成的beanDefinition注册到IOC容器中
registerBeanDefinition()
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) { String[] var4 = aliases; int var5 = aliases.length; for(int var6 = 0; var6 < var5; ++var6) { String alias = var4[var6]; registry.registerAlias(beanName, alias); } } }
- 主要有通过传来的参数注册器.registerBeanDefinition(),再就是注册别名。这里只看registerBeanDefinition()方法。
registerBeanDefinition()这里用的是DefaultListableBeanFactory,PS:XmlBeanFactory是继承的DefaultListableBeanFactory。
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 var9) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var9); } } BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName); if(oldBeanDefinition != null) { if(!this.isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound."); } if(oldBeanDefinition.getRole() < beanDefinition.getRole()) { 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(this.hasBeanCreationStarted()) { Map var4 = this.beanDefinitionMap; synchronized(this.beanDefinitionMap) { this.beanDefinitionMap.put(beanName, beanDefinition); //这种new一个新对象,处理完后,将需要修改的引用指向new的新对象,可以降低并发的影响,也就是避免多线程操作同一对象喽。 List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; if(this.manualSingletonNames.contains(beanName)) { Set<String> updatedSingletons = new LinkedHashSet(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 || this.containsSingleton(beanName)) { this.resetBeanDefinition(beanName); } }
- 可以看到最后IOC容器是基于
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
对象的,所有定义好的bean都是在这个线程安全的hashmap中存取的,而且Spring用到了大量的以空间换取“避免多个线程操作同一个对象”这种方法。
阅读全文
0 0
- Spring IOC 容器源码阅读笔记
- Spring Ioc容器阅读笔记
- Spring源码阅读-- IOC容器资源定位
- Spring源码阅读-- IOC容器资源解析
- Spring IoC容器在Web环境中的启动源码阅读
- Spring源码阅读之IoC容器初始化1 -- Resource定位
- Spring源码阅读(一):IOC容器的初始化
- Spring源码阅读(二)—IOC容器初始化
- Spring源码阅读(三)—IOC容器依赖注入
- Spring源码阅读--BeanDefinition 在 IOC 容器中的注册
- Spring源码阅读之IoC容器初始化3 -- BeanDefinition在IoC容器中的注册
- spring学习笔记:Spring IOC容器,Spring源码
- SPRING源码分析:IOC容器
- Spring 源码阅读二 IOC
- Spring源码阅读三 IOC
- Spring源码阅读 四 IOC
- Spring学习笔记:IOC容器
- Spring源码阅读之IoC容器初始化2 -- BeanDefinition载入与解析
- ibatis批量删除在配置文件中进行
- ajax获取json数据为多维数组时,前台js嵌套循环解析
- 操作系统 进程通信实验
- dict.setdefault(key, default=None)
- 存储知识、mount挂载理解
- Spring IOC 容器源码阅读笔记
- 通过hmmlearn学习使用HMM隐马尔科夫模型
- Java分布式跟踪系统Zipkin(七):Zipkin源码分析-Zipkin的源码结构
- 【Scikit-Learn 中文文档】数据集加载工具
- 第14章 统一接口配置UCI
- freemarker整合问题之--DEFAULT_INCOMPATIBLE_IMPROVEMENTS
- 如何在 Azure 门户中将托管数据磁盘附加到 Windows VM
- 扁平化管理 hihoCoder[Offer收割]编程练习赛38/hihoCoder1650
- jxl导出数据到excel表格