说到spring不得不提其两大特性IOC、AOP,本文主要介绍结合代码看下spring Ioc相关原理,阅读源码若是只是为了看源码效率就会很低,仍是要有必定的目的性,咱们结合着如下的问题去源码中找答案。本篇文章为《图灵学院》课程笔记java
以下图spring Ioc的总体架构图中能够看出,Spring启动时读取bean配置信息,并在spring中生成一份相应bean配置注册表,而后会根据注册表实例化Bean,而且装配好bean 之间的依赖关系,为上层应用提供bean实例,其中bean的缓存池是经过hashmap实现的git
spring.xml中保存了Bean的描述配置,BeanFactory读取这些配置而后生成bean,这是咱们对ioc原理的通常理解,深刻思考还会有更多问题产生web
ioc 实现中 咱们在xml 中描述的Bean信息最后 都将保存至BeanDefinition (定义)对象中,其中xml bean 与BeanDefinition 程一对一的关系。xml bean中设置的属性最后都会体如今BeanDefinition中spring
因而可知,xml bean中设置的属性最后都会体如今BeanDefinition中。如:缓存
**XML-bean ** | BeanDefinition |
---|---|
class | beanClassName |
scope | scope |
lazy-init | lazyInit |
constructor-arg | ConstructorArgument |
property | MutablePropertyValues |
factory-method | factoryMethodName |
destroy-method | AbstractBeanDefinition.destroyMethodName |
init-method | AbstractBeanDefinition.initMethodName |
autowire | AbstractBeanDefinition.autowireMode |
id | |
name |
在上表中咱们并无看到 xml bean 中的 id 和name属性没有体如今定义中,缘由是ID 其做为当前Bean的存储key注册到了BeanDefinitionRegistry 注册器中。name 做为别名key 注册到了 AliasRegistry 注册中心。其最后都是指向其对应的BeanDefinition。markdown
BeanDefinitionRegistry属性结构架构
BeanDefinitionReader(Bean定义读取)oop
如今咱们了解 BeanDefinition 中存储了Xml Bean信息,而BeanDefinitionRegister 基于ID和name 保存了Bean的定义。接下要学习的是从xml Bean到BeanDefinition 而后在注册至BeanDefinitionRegister 整个过程。学习
上图中能够看出Bean的定义是由BeanDefinitionReader 从xml 中读取配置并构建出 BeanDefinitionReader,而后在基于别名注册到BeanDefinitionRegister中。ui
BeanDefinitionReader结构
基于资源加载beanDefinition并注册到注册器
int loadBeanDefinitions(String var1)
基于资源路径加载beanDefinition并注册大屏注册器
BeanDefinitionRegistry getRegistry()
获取注册器
ResourceLoader getResourceLoader()
获取资源装载器
//建立一个简单注册器
BeanDefinitionRegistry register = new SimpleBeanDefinitionRegistry();
//建立bean定义读取器
BeanDefinitionReader reader = new XmlBeanDefinitionReader(register);
// 建立资源读取器
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
// 获取资源
Resource xmlResource = resourceLoader.getResource("spring.xml");
// 装载Bean的定义
reader.loadBeanDefinitions(xmlResource);
// 打印构建的Bean 名称
System.out.println(Arrays.toString(register.getBeanDefinitionNames());
复制代码
有了Bean的定义就至关于有了产品的配方,接下来就是要把这个配方送到工厂进行生产了。在ioc当中Bean的构建是由BeanFactory 负责的。其结构以下:
方法说明:
以上方法中重点要关注getBean,当用户调用getBean的时候就会触发 Bean的建立动做,其是如何建立的呢?
#建立Bean堆栈
// 其反射实例化Bean
java.lang.reflect.Constructor.newInstance(Unknown Source:-1)
BeanUtils.instantiateClass()
//基于实例化策略 实例化Bean
SimpleInstantiationStrategy.instantiate()
AbstractAutowireCapableBeanFactory.instantiateBean()
// 执行Bean的实例化方法
AbstractAutowireCapableBeanFactory.createBeanInstance()
AbstractAutowireCapableBeanFactory.doCreateBean()
// 执行Bean的建立
AbstractAutowireCapableBeanFactory.createBean()
// 缓存中没有,调用指定Bean工厂建立Bean
AbstractBeanFactory$1.getObject()
// 从单例注册中心获取Bean缓存
DefaultSingletonBeanRegistry.getSingleton()
AbstractBeanFactory.doGetBean()
// 获取Bean
AbstractBeanFactory.getBean()
// 调用的客户类
com.tuling.spring.BeanFactoryExample.main()
复制代码
Bean建立时序图:
从调用过程能够总结出如下几点:
BeanFactory 看上去能够去作IOC当中的大部分事情,为何还要去定义一个ApplicationContext 呢? ApplicationContext 结构图
从图中能够看到 ApplicationContext 它由BeanFactory接口派生而来,于是提供了BeanFactory全部的功能。除此以外context包还提供了如下的功能:
原文地址