- 浏览: 105157 次
- 性别:
- 来自: 北京
文章分类
最新评论
<spring.version>4.0.6.RELEASE</spring.version>
这一部分主要记录bean定义的解析和加载,包括注解方式定义的bean。
【UML】
首先以uml展示ioc过程的全貌,为避免干扰,每个类仅表述了核心的属性,方法和方法内的关键代码。
refresh()方法标橙色,是外部调用的入口,如ContextLoaderListener。
标红色的是一些关键属性和实现。
uml连接:http://dl2.iteye.com/upload/attachment/0115/8766/bedf264c-a530-33b3-924a-2b1799eef3ac.png
【代码解读】
XmlWebApplicationContext继承了AbstractApplicationContext。AbstractApplicationContext的refresh()方法对外提供访问入口,定义了bean定义的解析,创建和一些过程处理,如aop等。使用方法模版的设计模式,由各子类实现一些过程的细节。
在refresh()方法中,obtainFreshBeanFactory()方法负责beanFactory的创建及bean定义的解析逻辑,并让applicationContext持有beanFactory。
refreshBeanFactory()是一个抽象方法,具体实现是由AbstractRefreshableApplicationContext实现的。在这个方法中,如果已经存在beanFactory,则销毁beanFactory持有的bean定义及bean实例,并销毁beanFactory,代码实现上就是附null。然后创建一个新的beanFactory,具体实现类为DefaultListableBeanFactory。
loadBeanDefinitions()方法负责bean定义的解析,在AbstractRefreshableApplicationContext中是个抽象方法,由XmlWebApplicationContext实现。因为我们项目在web.xml配的是XmlWebApplicationContext。在这个方法中,会将beanFacotry以BeanDefinitionRegistry接口的实现放到XmlBeanDefinitionReader中,并让XmlBeanDefinitionReader持有beanFactory,以方便后面解析出beanDefinition后,可以注册到beanFactory中。当然实际持有beanFactory的是XmlBeanDefinitionReader的父类AbstractBeanDefinitionReader,可以参看UML图。
根据在web.xml定义的contextConfigLocation,由XmlBeanDefinitionReader开始解析每个配置文件。整体流程的代码实现在XmlBeanDefinitionReader的父类AbstractBeanDefinitionReader中。但bean定义的解析和加载在XmlBeanDefinitionReader中。
实际的bean定义解析也不是由XmlBeanDefinitionReader完成的,XmlBeanDefinitionReader会创建DefaultBeanDefinitionDocumentReader,并将自己作为XmlReaderContext的一个属性,交由DefaultBeanDefinitionDocumentReader进行处理,并由DefaultBeanDefinitionDocumentReader持有XmlReaderContext。
在DefaultBeanDefinitionDocumentReader解析bean定义的过程中,遇到非http://www.springframework.org/schema/beans命名空间的标签,会交由BeanDefinitionParserDelegate 进行解析。BeanDefinitionParserDelegate会持有DefaultBeanDefinitionDocumentReader的readerContext。
类似于注解和aop等的定义解析,都是由BeanDefinitionParserDelegate完成的,他会根据namespaceUri的不同,找到不同的NameSpaceHandler。查找的工作由readerContext持有的属性NamespaceHandlerResolver完成,对应的实现类是DefaultNamespaceHandlerResolver。而DefaultNamespaceHandlerResolver的创建,是在XMLBeanDefinitionReader在创建XmlReaderContext时,就已经指定的,可参考UML图,或者前面的代码解读。
NameSpaceHandler都放在DefaultNamespaceHandlerResolver的属性handlerMappings中,此处找到的实现类是NamespaceHandlerSupport。
NamespaceHandlerSupport的属性parsers中存放了所需的BeanDefinitionParser。以注解为例,会找到ComponentScanBeanDefinitionParser,处理注解的bean定义解析,并最终调用readerContext的fireComponentRegistered方法,向eventListener注册componentDefinition。
未完,待续 -=^^=-
这一部分主要记录bean定义的解析和加载,包括注解方式定义的bean。
【UML】
首先以uml展示ioc过程的全貌,为避免干扰,每个类仅表述了核心的属性,方法和方法内的关键代码。
refresh()方法标橙色,是外部调用的入口,如ContextLoaderListener。
标红色的是一些关键属性和实现。
uml连接:http://dl2.iteye.com/upload/attachment/0115/8766/bedf264c-a530-33b3-924a-2b1799eef3ac.png
【代码解读】
XmlWebApplicationContext继承了AbstractApplicationContext。AbstractApplicationContext的refresh()方法对外提供访问入口,定义了bean定义的解析,创建和一些过程处理,如aop等。使用方法模版的设计模式,由各子类实现一些过程的细节。
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } } }
在refresh()方法中,obtainFreshBeanFactory()方法负责beanFactory的创建及bean定义的解析逻辑,并让applicationContext持有beanFactory。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }
refreshBeanFactory()是一个抽象方法,具体实现是由AbstractRefreshableApplicationContext实现的。在这个方法中,如果已经存在beanFactory,则销毁beanFactory持有的bean定义及bean实例,并销毁beanFactory,代码实现上就是附null。然后创建一个新的beanFactory,具体实现类为DefaultListableBeanFactory。
@Override 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()方法负责bean定义的解析,在AbstractRefreshableApplicationContext中是个抽象方法,由XmlWebApplicationContext实现。因为我们项目在web.xml配的是XmlWebApplicationContext。在这个方法中,会将beanFacotry以BeanDefinitionRegistry接口的实现放到XmlBeanDefinitionReader中,并让XmlBeanDefinitionReader持有beanFactory,以方便后面解析出beanDefinition后,可以注册到beanFactory中。当然实际持有beanFactory的是XmlBeanDefinitionReader的父类AbstractBeanDefinitionReader,可以参看UML图。
@Override protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // Create a new XmlBeanDefinitionReader for the given BeanFactory. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // Configure the bean definition reader with this context's // resource loading environment. beanDefinitionReader.setEnvironment(getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // Allow a subclass to provide custom initialization of the reader, // then proceed with actually loading the bean definitions. initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); }
根据在web.xml定义的contextConfigLocation,由XmlBeanDefinitionReader开始解析每个配置文件。整体流程的代码实现在XmlBeanDefinitionReader的父类AbstractBeanDefinitionReader中。但bean定义的解析和加载在XmlBeanDefinitionReader中。
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException { String[] configLocations = getConfigLocations(); if (configLocations != null) { for (String configLocation : configLocations) { reader.loadBeanDefinitions(configLocation); } } }
实际的bean定义解析也不是由XmlBeanDefinitionReader完成的,XmlBeanDefinitionReader会创建DefaultBeanDefinitionDocumentReader,并将自己作为XmlReaderContext的一个属性,交由DefaultBeanDefinitionDocumentReader进行处理,并由DefaultBeanDefinitionDocumentReader持有XmlReaderContext。
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(); } } public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); documentReader.setEnvironment(this.getEnvironment()); int countBefore = getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; }
在DefaultBeanDefinitionDocumentReader解析bean定义的过程中,遇到非http://www.springframework.org/schema/beans命名空间的标签,会交由BeanDefinitionParserDelegate 进行解析。BeanDefinitionParserDelegate会持有DefaultBeanDefinitionDocumentReader的readerContext。
BeanDefinitionParserDelegate parent = this.delegate; this.delegate = createDelegate(this.readerContext, root, parent); preProcessXml(root); parseBeanDefinitions(root, this.delegate); postProcessXml(root); this.delegate = parent; 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); } }
类似于注解和aop等的定义解析,都是由BeanDefinitionParserDelegate完成的,他会根据namespaceUri的不同,找到不同的NameSpaceHandler。查找的工作由readerContext持有的属性NamespaceHandlerResolver完成,对应的实现类是DefaultNamespaceHandlerResolver。而DefaultNamespaceHandlerResolver的创建,是在XMLBeanDefinitionReader在创建XmlReaderContext时,就已经指定的,可参考UML图,或者前面的代码解读。
NameSpaceHandler都放在DefaultNamespaceHandlerResolver的属性handlerMappings中,此处找到的实现类是NamespaceHandlerSupport。
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { String namespaceUri = getNamespaceURI(ele); NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); }
NamespaceHandlerSupport的属性parsers中存放了所需的BeanDefinitionParser。以注解为例,会找到ComponentScanBeanDefinitionParser,处理注解的bean定义解析,并最终调用readerContext的fireComponentRegistered方法,向eventListener注册componentDefinition。
@Override public BeanDefinition parse(Element element, ParserContext parserContext) { String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(BASE_PACKAGE_ATTRIBUTE), ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); // Actually scan for bean definitions and register them. ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages); registerComponents(parserContext.getReaderContext(), beanDefinitions, element); return null; } protected void registerComponents( XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) { Object source = readerContext.extractSource(element); CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source); for (BeanDefinitionHolder beanDefHolder : beanDefinitions) { compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder)); } // Register annotation config processors, if necessary. boolean annotationConfig = true; if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) { annotationConfig = Boolean.valueOf(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE)); } if (annotationConfig) { Set<BeanDefinitionHolder> processorDefinitions = AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source); for (BeanDefinitionHolder processorDefinition : processorDefinitions) { compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition)); } } readerContext.fireComponentRegistered(compositeDef); }
未完,待续 -=^^=-
相关推荐
SpringIOC源码解说,以及对应的代码解读。
个人整理SpringIOC源码解读,望大婶们指点指点,后续继续添加
老王读 Spring IoC 系列文章的源码分析&测试代码 Spring IoC 源码分析,帮助大家学习 Spring 源码,更加了解 Spring 的底层 博客专栏地址:https://blog.csdn.net/wang489687009/category_11269905.html
Spring IoC源码深度剖析开源架构源码2021.pdf
这是spring_ioc部分的内容。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。...
Spring源码分析_Spring_IOC
Spring4 IOC 示例源码, 包含演示代码,以及所有涉及到的jar包。
Spring IoC 入门实例,包括了多种依赖注入方式,适合Spring初学者学习使用。实例里有详细的注释,一看就懂。
spring ioc容器初始化流程图 spring ioc容器依赖注入流程图 spring aop实现原理流程图
1.Spring入门和IOC介绍 2.对象依赖 3.AOP入门 4.JDBCTemplate和Spring事务 5.Spring事务原理 6.Spring事务的一个线程安全问题 7.IOC再回顾和面试题 8.AOP再回顾
Java进阶之SpringIoC源码深度剖析共19页.pdf.zip
springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC...
本文深入探讨了Spring框架中IoC容器的源码机制,涵盖了容器的初始化、Bean工厂的实例化、Bean定义的读取及Spring Bean的生命周期管理。通过精细的分析,本文揭示了AnnotationConfigApplicationContext的实例化过程,...
spring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demo...
spring ioc指的是控制反转,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。交由Spring容器统一进行管理,从而实现松耦合
SpringIoc示例代码,SpringIoc示例代码,SpringIoc示例代码,SpringIoc示例代码
1、 需要去构造一个Spring容器:ClassPathXmlApplicationContext; 2、 需要注解定义两个注解:@Service、@Resource; 3、 使用反射的手段读取指定目录下的class信息,解析Class信息; 4、 对Class信息的注解做处理...
spring Ioc容器配置 IOC容器数据源配置 <!-- 配置数据源 --> destroy-method="close"> <value>org.gjt.mm.mysql.Driver <value>jdbc:mysql://localhost:3306/demo <value>root ...
Spring Ioc源码分析系列--自动注入循环依赖的处理.doc
Spring Ioc源码分析系列--@Autowired注解的实现原理.doc