Spring 源码粘贴1 IoC

来源:互联网 发布:数控车床锥度螺纹编程 编辑:程序博客网 时间:2024/05/29 17:33

书籍 Spring技术内幕

文档 Spring官方文档

版本 Spring 4.3.8


第一部分.关于Spring IoC

反转控制/依赖注入

提到三个接口 BeanFactory ApplicationContext WebApplicationContext

继承关系


没有什么特别的理由就别用BeanFactory,更常用ApplicationContext,支持的功能更多(7.16).在第三方库或者是其他不使用Ioc的地方来获取Factory就需要使用这个单例的ContextSingletonBeanFactoryLocator

BeanFactory顶级接口,规定了基本的方法getBean(),子接口一步步增加方法.

XmlBeanFactory过时,使用它的父类DefaultListableBeanFactory搞事

        FileSystemResource resource = new FileSystemResource("spring.xml");//Resource定位        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);        reader.loadBeanDefinitions(resource);

IoC容器的初始化过程

1.Resource定位   通过各种资源加载器载入配置文件

2.BeanDefinition载入 将用户的Bean转换为IoC内部数据结构BeanDefinition

3.向IoC容器注册BeanDefinition  通过BeanDefinitionRegister接口将BeanDefinition注册到容器中

示例:FileSystemXmlApplicationContext 
看类图
基类AbstractApplicationContext继承自DefaultResourceLoader并实现了方法
protected Resource getResourceByPath(String path) {return new ClassPathContextResource(path, getClassLoader());}
FileSystemXmlApplicationContext类覆盖了此方法
@Overrideprotected Resource getResourceByPath(String path) {if (path != null && path.startsWith("/")) {path = path.substring(1);}return new FileSystemResource(path);}
使用FileSystemResource加载Resource
构造函数
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)throws BeansException {super(parent);setConfigLocations(configLocations);if (refresh) {refresh();}}
在构造函数中调用refresh(),该方法定义在基类AbstractApplicationContext
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.prepareRefresh();//这里就是去getResourceByPath()方法的入口咯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) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}}}

经过一系列的方法调用终于到了getResourceByPath(),就这样找到了xml文件
2.在AbstractXmlApplicationContext中 
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {...initBeanDefinitionReader(beanDefinitionReader);//设置读取xml的reader}
然后在AbstractBeanDefinitionReader中
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {...int loadCount = loadBeanDefinitions(resources);                ...}
然后调用几次后到达
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();int countBefore = getRegistry().getBeanDefinitionCount();documentReader.registerBeanDefinitions(doc, createReaderContext(resource));//这里就会通过resource来获取xml文件return getRegistry().getBeanDefinitionCount() - countBefore;}
具体到开始解析xml中的单个节点,从节点获取数据并创建BeanDefinition在此DefaultBeanDefinitionDocumentReader
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);...}
具体实现是BeanDefinitionParserDelegate
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {...                //这里面就是从elem解析<bean>创建一个BeanDefinitionAbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);...}
当然里面的内容还有很多
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {...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);//这里获取<bean>的儿子属性并添加到BeanDefinition中去parseQualifierElements(ele, bd);bd.setResource(this.readerContext.getResource());bd.setSource(extractSource(ele));return bd;...}
public void parsePropertyElements(Element beanEle, BeanDefinition bd) {NodeList nl = beanEle.getChildNodes();for (int i = 0; i < nl.getLength(); i++) {Node node = nl.item(i);if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {parsePropertyElement((Element) node, bd);}}}
原创粉丝点击