




已阅读5页,还剩29页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Spring源码解析-beanfactoryDemopublic class MyBeanTest public static void main(String args) BeanFactory ctx = new XmlBeanFactory(new ClassPathResource(spring.xml); MyBean testBean = (MyBean)ctx.getBean(testBean); System.out.println(testBean.getTestStr(); package qbb.spring.bean;public class MyBean private String testStr = testStr; public MyBean() public MyBean(String testStr) this.testStr = testStr; public String getTestStr() return testStr; public void setTestStr(String testStr) this.testStr = testStr; beans xmlns=/schema/beans xmlns:xsi=/2001/XMLSchema-instance xmlns:context=/schema/context xsi:schemaLocation=/schema/beans uml类图上次看的时候就画过这个图,这次做了细化和调整。XmlBeanFactory继承关系AliasRegistry定义对Alias的简单增删改等操作;SimpleAliasRegistry使用currenthashmap作为缓存,并对接口AliasRegisty进行实现;SingletonBeanRegistry定义对单例的获取及获取;DefaultSingletonBeanRegistry是SingletonBeanRegistry的实现;FactoryBeanRegistrySupport在DefaultSingletonBeanRegistry基础上,增加对FactorBean的特殊处理功能;BeanFactory定义获取bean及bean的各种属性;HierarchicalBeanFactory继承BeanFactory,增加对parentFactory的支持;ConfigurableBeanFactory提供配置各种factory的方法;ListableBeanFactory根据不同条件获取bean的配置清单;AutowireCapableBeanFactory提供创建bean,自动注入,初始化已经应用bean后的处理器;AbstractBeanFactory综合FactoryBeanRegistrySupport和ConfigurableBeanFactory功能;ConfigurableListableBeanFactory是BeanFactory的配置清单,指定忽略类型和接口等;AbstractAutowireCapableBeanFactory综合AbstractBeanFactory并对接口AutowireCapalbeBeanFactory的实现;BeanDefinitionRegistry定义对BeanDefinition的curd操作;DefaultListableBeanFactory综合所有功能,主要是bean注册后的处理;XmlBeanFactory对DefaultListableBeanFactory类进行了扩展,主要是从xml文档读取BeanDefinition,对于注册以及获取Bean都是从父类DefaultLisstableBean继承的方法去实现,与父类的不同就是增加了XmlBeanDefinitionReader类型的reader属性,在XmlBeanFactory中主要使用reader属性对资源文件进行读取和注册;XmlBeanDefinitionReaderEnvironmentCapable定义获取Environment的方法;BeanDefinitionReader主要定义资源文件读取并转化为BeanDefinition的各种功能;AbstractBeanDefinitionReader对接口的实现;ResourceLoader资源加载器,根据给定的资源文件地址返回对应的Resource;DocumentLoader资源文件转化为Document的功能;BeanDefinitionDocumentReader读取Document并注册BeanFinition的功能;BeanDefinitionParserDelegate定义解析element的各种方法;BeanDefinitionBeanDefinition配置文件bean元素在容器的内部表现形式;ChildBeanDefinition父子bean中的子bean;GenericBeanDefinition2.5后加入,一站式的服务类;RootBeanDefinition对应一般性的bean元素标签,父子bean中的父bean可以用此表示,没有父bean的bean也使用来表示;xml解析beanDefinitionBeanFactory ctx = new XmlBeanFactory(new ClassPathResource(spring.xml);资源文件抽象new ClassPathResource(spring.xml)spring将外部的资源封装成内部使用Resource,可以从文件,class,jar,还有context上下文:我这里使用ClassPathResource加载spring文件,当然也可以使用FileSystemResource从文件系统路径加载。loadBeanDefinitionnew XmlBeanFactory(new ClassPathResource(spring.xml);调用XmlBeanFactory构造/ XmlBeanFactorypublic XmlBeanFactory(Resource resource) throws BeansException this(resource, null);public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException super(parentBeanFactory); this.reader.loadBeanDefinitions(resource);在条用super的时候会设置parentBeanFactory,好像只要mvc的时候才看到设置,其他地方基本没用到。/AbstractAutowireCapableBeanFactorypublic AbstractAutowireCapableBeanFactory(BeanFactory parentBeanFactory) this(); setParentBeanFactory(parentBeanFactory);public AbstractAutowireCapableBeanFactory() super(); /忽略一些依赖,在getbean的时候,在实例化属性填充后,会检查设置这些依赖关系, /然后再去调用实现InitializingBean的afterPropertiesSet方法和自定义的Init-Method ignoreDependencyInterface(BeanNameAware.class); ignoreDependencyInterface(BeanFactoryAware.class); ignoreDependencyInterface(BeanClassLoaderAware.class);/AbstractBeanFactorypublic void setParentBeanFactory(BeanFactory parentBeanFactory) if (this.parentBeanFactory != null & this.parentBeanFactory != parentBeanFactory) throw new IllegalStateException(Already associated with parent BeanFactory: + this.parentBeanFactory); this.parentBeanFactory = parentBeanFactory;在这些完了后会调用/xmlbeanfactorythis.reader.loadBeanDefinitions(resource);XmlBeanFactory使用XmlBeanDefinitionReader来解析和注册bean定义。/XmlBeanDefinitionReaderpublic int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException /EncodedResource做了编码处理,getReader时如果有编码就使用,没有就不适用 return loadBeanDefinitions(new EncodedResource(resource);public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException . try InputStream inputStream = encodedResource.getResource().getInputStream(); try InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) inputSource.setEncoding(encodedResource.getEncoding(); return doLoadBeanDefinitions(inputSource, encodedResource.getResource(); finally inputStream.close(); .看了下,spring中习惯doXXX来表示真正干活的代码,XXX来做主流程控制。自己写代码的时候有时流程会不清晰,会乱,后来还是从spring里面学会这招,先提炼主流程,然后再分配。/XmlBeanDefinitionReaderprotected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException try int validationMode = getValidationModeForResource(resource); Document doc = this.documentLoader.loadDocument( inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware(); return registerBeanDefinitions(doc, resource); .xml文件校验和解析/XmlBeanDefinitionReaderint validationMode = getValidationModeForResource(resource); Document doc = this.documentLoader.loadDocument( inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware();xml文档的2种校验方式:DTD和XSD,通过getValidationModeForResource来获取,DTD的会包含DOCTYPE,所以通过解析这个是否存在判断。校验过后就是通过DefaultDocumentLoader将xml文件解析Document,xml文件解析一般就是SAX、Dom、jdom,dom4j。registerBeanDefinitions/XmlBeanDefinitionReaderpublic int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException /将DefaultBeanDefinitionDocumentReader转为BeanDefinitionDocumentReader BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); /this.getEnvironment()获取到的是StandardEnvironment,可以用来获取系统变量和环境变量 documentReader.setEnvironment(this.getEnvironment(); int countBefore = getRegistry().getBeanDefinitionCount(); /使用DefaultBeanDefinitionDocumentReader解析document documentReader.registerBeanDefinitions(doc, createReaderContext(resource); return getRegistry().getBeanDefinitionCount() - countBefore;protected XmlReaderContext createReaderContext(Resource resource) if (spaceHandlerResolver = null) /DefaultNamespaceHandlerResolver,主要用来获取标签的解析, /特别是自定义标签的解析,后面单独讲下这个,里面最重要的方法NamespaceHandler resolve(String namespaceUri) spaceHandlerResolver = createDefaultNamespaceHandlerResolver(); return new XmlReaderContext(resource, blemReporter, this.eventListener, this.sourceExtractor, this, spaceHandlerResolver);最终还是委托DefaultBeanDefinitionDocumentReader来解析Document。/DefaultBeanDefinitionDocumentReaderpublic 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) /profile属性,类似maven -p,可以定义不同环境下的bean定义,配合环境变量files.active使用 String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec) Assert.state(this.environment != null, environment property must not be null); String specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); if (!this.environment.acceptsProfiles(specifiedProfiles) return; / any nested elements will cause recursion in this method. In / order to propagate and preserve default-* attributes correctly, / keep track of the current (parent) delegate, which may be null. Create / the new (child) delegate with a reference to the parent for fallback purposes, / then ultimately reset this.delegate back to its original (parent) reference. / this behavior emulates a stack of delegates without actually necessitating one. BeanDefinitionParserDelegate parent = this.delegate; / BeanDefinitionParserDelegate this.delegate = createHelper(readerContext, root, parent); preProcessXml(root); /子类实现 parseBeanDefinitions(root, this.delegate); postProcessXml(root); /子类实现 this.delegate = parent;protected BeanDefinitionParserDelegate createHelper(XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext, environment); delegate.initDefaults(root, parentDelegate); return delegate;/BeanDefinitionParserDelegatepublic void initDefaults(Element root, BeanDefinitionParserDelegate parent) populateDefaults(this.defaults, (parent != null ? parent.defaults : null), root); this.readerContext.fireDefaultsRegistered(this.defaults);/收集一些默认属性protected void populateDefaults(DocumentDefaultsDefinition defaults, DocumentDefaultsDefinition parentDefaults, Element root) String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE); if (DEFAULT_VALUE.equals(lazyInit) lazyInit = parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE; defaults.setLazyInit(lazyInit); String merge = root.getAttribute(DEFAULT_MERGE_ATTRIBUTE); if (DEFAULT_VALUE.equals(merge) merge = parentDefaults != null ? parentDefaults.getMerge() : FALSE_VALUE; defaults.setMerge(merge); String autowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE); if (DEFAULT_VALUE.equals(autowire) autowire = parentDefaults != null ? parentDefaults.getAutowire() : AUTOWIRE_NO_VALUE; defaults.setAutowire(autowire); / dont fall back to parentDefaults for dependency-check as its no / longer supported in as of 3.0. Therefore, no nested / would ever need to fall back to it. defaults.setDependencyCheck(root.getAttribute(DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE); if (root.hasAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE) defaults.setAutowireCandidates(root.getAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE); else if (parentDefaults != null) defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates(); if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE) defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE); else if (parentDefaults != null) defaults.setInitMethod(parentDefaults.getInitMethod(); if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE) defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE); else if (parentDefaults != null) defaults.setDestroyMethod(parentDefaults.getDestroyMethod(); defaults.setSource(this.readerContext.extractSource(root);parseBeanDefinitions/DefaultBeanDefinitionDocumentReaderprotected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) /默认是bean 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) /解析默认bean定义 parseDefaultElement(ele, delegate); else /自定义 delegate.parseCustomElement(ele); else /自定义 delegate.parseCustomElement(root); private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) /import if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT) importBeanDefinitionResource(ele); /别名 else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT) processAliasRegistration(ele); /bean else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT) processBeanDefinition(ele, delegate); /beans里面嵌套的bean解析 else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT) / recurse doRegisterBeanDefinitions(ele); /BeanDefinitionParserDelegatepublic boolean isDefaultNamespace(String namespaceUri) /BEANS_NAMESPACE_URI = /schema/beans; return (!StringUtils.hasLength(namespaceUri) | BEANS_NAMESPACE_URI.equals(namespaceUri);public boolean isDefaultNamespace(Node node) return isDefaultNamespace(getNamespaceURI(node);可以看到这里的Document解析节点是先校验是否为默认bean的namespace,是的话就判断节点是import、alias、bean,不是就按照自定义namespace方式解析。对于import的解析时循环解析import的Resource文件,alias是注册别名到map(会校验是否存在别名的循环定义),最核心的还是bean的解析。processBeanDefinition/DefaultBeanDefinitionDocumentReaderprotected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) /委托DefaultBeanDefinitionDocumentReader完成bean解析,最终bdHolder持有beanDefinition和beanName,别名 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) /是否有自定义属性需要处理 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try / Register the final decorated instance. 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); /注册beanDefinition和别名public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException / Register bean definition under primary name. String beanName = definitionHolder.getBeanName(); registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition(); / Register aliases for bean name, if any. String aliases = definitionHolder.getAliases(); if (aliases != null) for (String aliase : aliases) registry.registerAlias(beanName, aliase); delegate-parseBeanDefinitionElement(ele)/BeanDefinitionParserDelegatepublic BeanDefinitionHolder parseBeanDefinitionElement(Element ele) return parseBeanDefinitionElement(ele, null);public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) /bean的id和name属性 String id = ele.getAttribute(ID_ATTRIBUTE); String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); /name多个的情况,放入别名 List aliases = new ArrayList(); 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(No XML id specified - using + beanName + as bean name and + aliases + as aliases); if (containingBean = null) /检查名称是否用过,会有Set存储用过的名称 checkNameUniqueness(beanName, aliases, ele); /解析bean的element成最终的beanDefinition AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) /名称不存在就spring生成一个 if (!StringUtils.hasText(beanName) try if (containingBean != null) beanName = BeanDefinitionReaderUtils.generateBeanName( beanDefinition, this.readerContext.getRegistry(), true); else beanName = this.readerContext.generateBeanName(beanDefinition); / Register an alias for the plain bean class name, if still possible, / if the generator returned the class name plus a suffix. / This is expected for Spring 1
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025-2030中国液压剪式升降机行业市场现状供需分析及投资评估规划分析研究报告
- 出院计划与健康教育试题及答案
- 2025-2030中国浴室厨房用品行业市场现状供需分析及重点企业投资评估规划分析研究报告
- 医学电生理技术试题及答案
- 2025-2030中国波纹金属板行业市场现状供需分析及投资评估规划分析研究报告
- 2025-2030中国泄漏试验设备行业市场现状供需分析及投资评估规划分析研究报告
- 教师资格笔试考情分析试题及答案
- 心理咨询师考试中实践技巧与理论知识结合的试题答案
- 家电趣味测试题及答案
- 第12课《我是小小消防员》(教学设计)苏少版六年级上册综合实践活动
- 高中物理必修三《电磁感应现象的应用》说课课件
- 初中数学分层教学模式的实践与研究
- LNG加气站施工组织设计方案
- 2024年河北省邢台市中考一模理综物理试题(解析版)
- DL∕T 1753-2017 配网设备检修试验规程
- CJ/T 120-2016 给水涂塑复合钢管
- 第三单元山野放歌-《上去高山望平川》教学设计 2023-2024学年 人音版初中音乐八年级下册教案1000字
- 深基坑专项方案论证流程
- 《创业基础》课件-第五章 创业计划
- 列宁人物课件
- 八年级数学下册期中考试题(可打印)
评论
0/150
提交评论