Spring源码分析
Spring整体架构
1.Core Container
1. core
主要包含了spring框架基本的的核心工具类,spring的其他组件都要用到这个包,core模块是其他组件的基本核心。
2. beans
包含了访问spring配置文件,创建并管理bean以及进行IOC和DI操作相关的所有类。
3. context
为spring核心提供了大量扩展,添加了对国际化,事件传播,资源加载和对context的透明创建和支持。context同时也支持J2EE的一些特性,如EJB,JMX和基础的远程处理。ApplicationContext接口是Context模块的关键。
4. expression
提供了强大的表达式语言,用于在运行时查询和操纵对象。
2.Data Acess/Integration
1. JDBC
包含了Spring对JDBC数据访问进行封装的所有类。
2. ORM
为对象-关系映射的API,如Hibernate,iBatis等,提供了一个交互层。利用ORM的封装包,可以混合使用所有Spring提供的特性进行O/R映射。
3. OXM
提供了一个对Object/XML映射实现的抽象层。
4. JMS
主要包含了一些制造和消费信息的特性。
5. Transactions
支持编程和声明性的事务管理,这些事务必须实现特定的接口,并且岁所有的POJO都适用。
3.Web
1. Web模块
提供了基础的面向Web的集成特性,例如,多文件上传,使用servlet listeners初始化IOC容器以及一个面向Web的应用上下文。
2. Web-Servlet
包含了SpringMVC的实现。
3. Web-Porlet
提供了用于Portlet环境和Web-Servlet模块的MVC实现。
4.AOP
提供了面向切面编程的实现,Spring AOP模块为基于Spring的应用程序中的对象提供了事务管理服务。
5.Test
支持适用JUnit和TestNG对Spring组件进行测试。
容器的基本实现
//scope :方法作用域,如public,private,protect //returnt-type:方法返回值类型
//fully-qualified-class-name:方法所在类的完全限定名称 //parameters 方法参数
execution(< scope> < return-type> < fully-qualified-class-name>.*(parameters))
注意这一块,如果没有精确到class-name,而是到包名就停止了,要用两个"…"来表示包下的任意类:
execution(* com.zdy…(…)):com.zdy包下所有类的所有方法.
execution( com.zdy.Dog.*(…)): Dog类下的所有方法.
Spring IOC 容器源码分析
- BeanDefinition 就是我们所说的 Spring 的 Bean,我们自己定义的各个 Bean 其实会转换成一个个BeanDefinition 存在于 Spring 的 BeanFactory 中。
- 所以,如果有人问你 Bean 是什么的时候,你要知道 Bean 在代码层面上可以认为是 BeanDefinition 的实例。
- BeanDefinition 中保存了我们的 Bean 信息,比如这个 Bean 指向的是哪个类、是否是单例的、是否懒加载、这个 Bean 依赖了哪些 Bean 等等。
IOC步骤:
@Override
public void refresh() throws BeansException, IllegalStateException {
// 来个锁,不然 refresh() 还没结束,你又来个启动或销毁容器的操作,那不就乱套了嘛
synchronized (this.startupShutdownMonitor) {
// 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
prepareRefresh();
// 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
// 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
// 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
// 这块待会会展开说
prepareBeanFactory(beanFactory);
try {
// 【这里需要知道 BeanFactoryPostProcessor 这个知识点,Bean 如果实现了此接口,
// 那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。】
// 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
// 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
postProcessBeanFactory(beanFactory);
// 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 回调方法
invokeBeanFactoryPostProcessors(beanFactory);
// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。这里仅仅是注册,之后会看到回调这两方法的时机
registerBeanPostProcessors(beanFactory);
// 初始化当前 ApplicationContext 的 MessageSource,国际化这里就不展开说了,不然没完没了了
initMessageSource();
// 初始化当前 ApplicationContext 的事件广播器,这里也不展开了
initApplicationEventMulticaster();
// 从方法名就可以知道,典型的模板方法(钩子方法),不展开说
// 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
onRefresh();
// 注册事件监听器,监听器需要实现 ApplicationListener 接口。这也不是我们的重点,过
registerListeners();
// 重点,重点,重点
// 初始化所有的 singleton beans
//(lazy-init 的除外)
finishBeanFactoryInitialization(beanFactory);
// 最后,广播事件,ApplicationContext 初始化完成,不展开
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.
// 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// 把异常往外抛
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
- 从 ClassPathXmlApplicationContext 的构造方法说起,首先进入它的refresh方法。
(这里简单说下为什么是 refresh(),而不是 init() 这种名字的方法。因为ApplicationContext 建立起来以后,其实我们是可以通过调用 refresh() 这个方法重建的,refresh()会将原来的 ApplicationContext 销毁,然后再重新执行一次初始化操作。)
- 然后进入AbstractApplicationContext 的prepareRefresh()方法,该方法记录启动时间,并检验XML文件。
- 之后创建 Bean 容器,加载并注册 Bean。也就是refresh() 方法中的下一行 obtainFreshBeanFactory()方法(用来返回一个BeanFactory)。这个方法是全文最重要的部分之一,这里将会初始化 BeanFactory、加载 Bean、注册 Bean 等等。当然,这步结束后,Bean 并没有完成初始化。这里指的是 Bean 实例并未在这一步生成。
- obtainFreshBeanFactory()方法的refreshBeanFactory()方法中,这个方法生成一个BeanFactory实例( DefaultListableBeanFactory类型)
- 然后执行customizeBeanFactory(beanFactory)方法,就是配置是否允许 BeanDefinition 覆盖、是否允许循环引用。
- 接下来是最重要的 loadBeanDefinitions(beanFactory) 方法了,这个方法将根据配置,加载各个 Bean,然后放到 BeanFactory 中。读取配置的操作在 XmlBeanDefinitionReader 中,其负责加载配置、解析。
- 根据 之类的标签创建了一个 BeanDefinitionHolder 实例,这个实例里面也就是一个 BeanDefinition 的实例和它的 beanName、aliases 这三个信息。然后我们准备注册这个 BeanDefinition,最后,把这个注册事件发送出去。
- 然后进入BeanDefinitionReaderUtils的registerBeanDefinition方法注册Bean,所有的 Bean 注册后会放入这个 beanDefinitionMap 中。
到这里已经初始化了 Bean 容器(只进行到obtainFreshBeanFactory()方法), 配置也相应的转换为了一个个 BeanDefinition,然后注册了各个 BeanDefinition 到注册中心,并且发送了注册事件。
- 执行prepareBeanFactory方法,对一些特殊的 bean 进行了处理。
- finishBeanFactoryInitialization(beanFactory)会负责初始化所有的 singleton beans,执行方法里最后的beanFactory.preInstantiateSingletons()方法进行初始化所有非懒加载的bean。
- 接着就进入到 getBean(beanName) 方法了,这个方法我们经常用来从 BeanFactory 中获取一个 Bean,而初始化的过程也封装到了这个方法里。这里面要开始创建Bean了(如果是单例且已经创建,就直接返回),执行createBean(String beanName, RootBeanDefinition mbd, Object[] args)最后 return (T) bean。
- createBean中有个真正的执行方法doCreateBean,doCreateBean 中有三个细节很重要;一个是创建 Bean 实例的 createBeanInstance 方法,一个是依赖注入的 populateBean 方法,还有就是回调方法 initializeBean。
总结:
一个是 xml映射load成BeanDefinitions然后register到beanFactory,然后就是bean的初始化。有的bean是启动时候可以初始化,有的bean是懒初始化 getBean的时候初始化。