前言
Spirng:
1. 通过配置方式来创建对象,管理对象之间依赖关系(IOC)。
2. 还提供像通用日志记录、性能统计、安全控制、异常处理等面向切面的能力(AOP)。
3. 管理数据库事务。
4. 提供了一套简单的JDBC访问实现,提供与第三方数据访问框架集成。
5. 与第三方Web框架无缝集成,而且自己也提供了一套Spring MVC框架,来方便Web层搭建。
Spring的优点:
IOC:轻量级的容器。
AOP:通过在编译期间、装载期间或运行期间实现在不修改源代码的情况下给程序动态添加功能的一种技术。
简单的数据库事务管理。
JDBC抽象及ORM框架支持。
各种第三方框架的整合。
Spring IOC 容器的加载
大体上经过以下几个过程: 资源文件定位 、 解析 、 注册 、 实例化
IOC的初始化过程 ( obtainFreshBeanFactory() )
初始化的过程主要就是读取 XML资源到 Resource,并解析成 BeanDefinition,最终注册到 BeanFactory 中。
顶层调用:
1. 创建 ClassPathXmlApplicationContext,继而调用 AbstractApplicationContext 的 refresh() 方法进行刷新。
2. 创建并初始化 BeanFactory
AbstractApplicationContext.obtainFreshBeanFactory()
obtainFreshBeanFactory() 方法:
首先通过 refreshBeanFactory() 方法,创建了 DefaultListableBeanFactory 的实例,并进行初始化。
核心的 AbstractRefreshableApplicationContext.loadBeanDefinitions(beanFactory):
首先会创建一个 XmlBeanDefinitionReader 的实例:
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
AbstractXmlApplicationContext.loadBeanDefinitions(beanDefinitionReader):配置文件的加载、解析、注册
loadBeanDefinitions(beanDefinitionReader):配置文件的加载、解析、注册
资源文件定位:
1. 创建处理每一个 Resource
Resource[] configResources = AbstractXmlApplicationContext.getConfigResources()
解析:
2. 处理XML中的每一个元素
AbstractBeanDefinitionReader.loadBeanDefinitions((Resource)resource)
Document doc = XmlBeanDefinitionReader.doLoadDocument(inputSource, resource);
int count = XmlBeanDefinitionReader.registerBeanDefinitions(doc, resource);
DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)
3. 解析每一个 Bean
DefaultBeanDefinitionDocumentReader.processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele) //实际的解析工作是委托给BeanDefinitionParserDelegate完成
注册:
4. 注册每一个 Bean
BeanDefinitionReaderUtils.registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
registry.registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
DefaultListableBeanFactory.beanDefinitionMap.put(beanName, beanDefinition)
注册的实质就是以 beanName 为 key,以 beanDefinition 为 value,将其 put 到 HashMap 中。
IOC的初始化过程:实例化
如果 bean 没有设置 lazy-init (延迟加载)属性,那么 bean 的实例就会在初始化 IOC 完成之后,及时地进行初始化。
初始化时会先建立实例,然后根据配置利用反射对实例进行进一步操作。
AbstractApplicationContext.finishBeanFactoryInitialization(beanFactory)
beanFactory.preInstantiateSingletons() //初始化未设置延迟加载的Bean
DefaultListableBeanFactory.getBean(beanName)
AbstractBeanFactory.doGetBean(name, (Class)null, (Object[])null, false)
AbstractBeanFactory.createBean(beanName, mbd, args)
AbstractAutowireCapableBeanFactory.doCreateBean(beanName, mbdToUse, args)
BeanWrapper instanceWrapper = AbstractAutowireCapableBeanFactory.createBeanInstance(beanName, mbd, args) //创建bean的实例
AbstractAutowireCapableBeanFactory.populateBean(beanName, mbd, instanceWrapper) //初始化Bean(通过反射注入属性等)
DefaultSingletonBeanRegistry private final Map<String, Object> disposableBeans = new LinkedHashMap(); //Bean对象存放在Map中
IOC 面试汇总
Spring 的 IoC 设计支持以下功能:
依赖注入
依赖检查
自动装配
支持集合
指定初始化方法和销毁方法
IOC 中最基本的技术就是 反射(Reflection):
根据配置文件中给出的类名生成相应的 Bean对象。
IOC 优点:
内存控制:统一管理对象,避免对象乱创建导致额外的内存开销。
降低耦合度:将设计好的对象交给 Ioc容器 控制,通过依赖注入,由容器管理对象的生命周期、依赖关系,实现解耦。
Bean的作用域:
1. “singleton”(单例,通过单例缓存池实现)
2. “prototype”(原型,每次创建全新的bean)
IOC 容器:
BeanFactory(低级容器):
BeanFactory 粗暴简单,可以理解为就是个 HashMap,Key 是 BeanName,Value 是 Bean 实例。
通常只提供注册(put),获取(get)这两个功能。我们可以称之为 “低级容器”。
ApplicationContext(高级容器):
支持不同的信息源头,可以访问文件资源,支持应用事件
高级容器依赖低级容器:
低级容器加载配置文件(从 XML,数据库,Applet),并解析成 BeanDefinition 到低级容器中。
加载成功后,高级容器启动高级功能,例如接口回调,监听器,自动实例化单例,发布事件等功能。
ClassPathXmlApplicationContext 访问了 “抽象高级容器” 的 refresh 方法:
refresh 回调 低级容器 的 refreshBeanFactory 方法,
这个方法的作用是使用低级容器加载所有 BeanDefinition 和 Properties 到容器中。
低级容器加载成功后,高级容器开始处理一些回调,例如 Bean 后置处理器,
回调 setBeanFactory 方法,或者注册监听器等,发布事件,实例化单例 Bean 等功能。
getBean() 的操作都是在低级容器里操作
依赖注入:
加载所有的 Bean 配置成 BeanDefinition 到容器中,如果 Bean 有依赖关系,则使用占位符暂时代替。
然后,在调用 getBean 的时候,进行真正的依赖注入,即如果碰到了属性是 ref 的占位符,那么就从容器里获取这个 Bean,
然后注入到实例中。
依赖注入只需要 “低级容器” 就可以实现。
getBean():
从 BeanDefinition 所属的 Map 里,拿出 Class 对象进行实例化,
同时,如果有依赖关系,将递归调用 getBean 方法,完成依赖注入。