说到spring不得不提其两大特性IOC、AOP,本文主要介绍结合代码看下spring Ioc相关原理,阅读源码如果只是为了看源码效率就会很低,还是要有一定的目的性,我们结合着以下的问题去源码中找答案。
如下图spring Ioc的整体架构图中可以看出,Spring启动时读取bean配置信息,并在spring中生成一份相应bean配置注册表,然后会根据注册表实例化Bean,并且装配好bean 之间的依赖关系,为上层应用提供bean实例,其中bean的缓存池是通过hashmap实现的
spring.xml中保存了Bean的描述配置,BeanFactory读取这些配置然后生成bean,这是我们对ioc原理的一般理解,深入思考还会有更多问题产生
BeanDefinition(Bean定义)
ioc 实现中 我们在xml 中描述的Bean信息最后 都将保存至BeanDefinition (定义)对象中,其中xml bean 与BeanDefinition 程一对一的关系。xml bean中设置的属性最后都会体现在BeanDefinition中
由此可见,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 |
BeanDefinition 属性结构
BeanDefinitionRegistry(Bean注册器)
在上表中我们并没有看到 xml bean 中的 id 和name属性没有体现在定义中,原因是ID 其作为当前Bean的存储key注册到了BeanDefinitionRegistry 注册器中。name 作为别名key 注册到了 AliasRegistry 注册中心。其最后都是指向其对应的BeanDefinition。
BeanDefinitionRegistry属性结构
BeanDefinitionReader(Bean定义读取)
现在我们了解 BeanDefinition 中存储了Xml Bean信息,而BeanDefinitionRegister 基于ID和name 保存了Bean的定义。接下要学习的是从xml Bean到BeanDefinition 然后在注册至BeanDefinitionRegister 整个过程。
上图中可以看出Bean的定义是由BeanDefinitionReader 从xml 中读取配置并构建出 BeanDefinitionReader,然后在基于别名注册到BeanDefinitionRegister中。
BeanDefinitionReader结构
int loadBeanDefinitions(Resource var1)
基于资源加载beanDefinition并注册到注册器
int loadBeanDefinitions(String var1)
基于资源路径加载beanDefinition并注册大屏注册器
BeanDefinitionRegistry getRegistry()
获取注册器
ResourceLoader getResourceLoader()
获取资源装载器
基于示例演示BeanDefinitionReader装载过程
//创建一个简单注册器 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的创建动作,其是如何创建的呢?
演示基本BeanFactory获取一个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包还提供了以下的功能: