Spring源码分析
2021/6/14 20:22:56
本文主要是介绍Spring源码分析,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
关键类介绍
ApplicationContext
万能的 applicationContext, 但实际上各种能力都是依赖于其他的类, 比如 getBean 是 beanFactory 的, publishEvent 是事件广播器的, 等等. 其本身是一个综合体, 整合这些能力, 便于开发者调用和理解. # 下面列一下相关的接口, 抽象类, 和具体类 ApplicationContext 是一个只读的 bean 容器 可以加载解析配置文件(如xml) 可以发布事件和注册监听 具有国际化消息处理能力 ConfigurableApplicationContext 是一个具有可配置能力的 容器(可设置各个参数, 如id, 父容器) 具有容器生命周期概念, 如启动,停止,关闭. AbstractApplicationContext 模板方法模式的抽象类, 定义了容器的模板(refresh方法), 但由具体的子类实现部分方法 管理Bean和BeanFactory的PostProcessor 管理事件的监听和处理 AbstractRefreshableApplicationContext 为可重复刷新的容器提供基类 加入了BeanFactory的管理(创建/关闭等) AbstractRefreshableConfigApplicationContext 加入了configLocation字段, 用于某些容器初始化BeanFactory和Bean AbstractXmlApplicationContext 定义了读取xml配置文件来加载BeanFactory的代码, 使得子类只需提供配置文件地址或Resource ClassPathXmlApplicationContext 继承基类, 提供配置文件地址的构造方法, 调用refresh加载BeanFactory
BeanFactory
1.核心中的核心, 加载和管理 beanDefinitions(Bean配置信息), 创建和管理 bean 对象实例, 注册和管理 BeanPostProcessor(Bean扩展) # 下面列一下相关的接口, 抽象类, 和具体类 BeanFactory 定义了 Bean 的基础操作接口, 如 getBean, getType, isSingleton 等 SingletonBeanRegistry 定义了单例对象的操作接口 (注册/获取/是否已存在) HierarchicalBeanFactory 定义了父 BeanFactory 的相关操作接口(获取) ConfigurableBeanFactory 定义了对 BeanFactory 做各种配置的操作接口, 包括 BeanPostProcessor, setParentBeanFactory, destroyBean, registerAlias, resolveAliases 等 DefaultSingletonBeanRegistry 实现了 SingletonBeanRegistry 接口, 即实现了单例对象的缓存管理, 包括一级/二级/三级(二级三级只依赖循环用上的两个缓存) FactoryBeanRegistrySupport 继承了 DefaultSingletonBeanRegistry 实现对使用 FactoryBean 存储和获取 bean 对象实例方式的支持 AbstractBeanFactory 继承了 FactoryBeanRegistrySupport 实现了 BeanFactory/HierarchicalBeanFactory/ConfigurableBeanFactory 定义的接口 实现了具体 getBean, 包括缓存管理等 AutowireCapableBeanFactory 定义了根据 class 类型获取 BeanDefinition 信息以及 Bean 对象的接口 AbstractAutowireCapableBeanFactory 继承自 AbstractBeanFactory 实现了 AutowireCapableBeanFactory 中定义的方法(就是实现了根据 class 获取 bean 或 BeanDefinition) 实现了 createBean, 也就是真正的实例化一个对象的过程, 包括实例化, 为需要赋值的字段注入相应的值 同时触发了 BeanPostProcessor 的方法调用 BeanDefinitionRegistry 定义了 BeanDefinition 的注册/获取/移除 ListableBeanFactory 定义了 BeanDefinition 的可遍历性 ConfigurableListableBeanFactory 结合 ListableBeanFactory 和 ConfigurableBeanFactory 并补充完善了几个相关接口 (如 getBeanNamesIterator 接口 ) DefaultListableBeanFactory 继承了 AbstractAutowireCapableBeanFactory 实现了 BeanDefinitionRegistry/ConfigurableListableBeanFactory 的接口 # 总结: 定义处: BeanFactory(getBean) SingletonBeanRegistry(addSingleton) HierarchicalBeanFactory(getParentBeanFactory) ConfigurableBeanFactory(addBeanPostProcessor) AutowireCapableBeanFactory(autowireBean) BeanDefinitionRegistry(registerBeanDefinition) ListableBeanFactory(getBeanDefinitionNames) ConfigurableListableBeanFactory(getBeanNamesIterator) 实现处: DefaultSingletonBeanRegistry(registerSingleton) FactoryBeanRegistrySupport(getObjectFromFactoryBean) AbstractBeanFactory(doGetBean) AbstractAutowireCapableBeanFactory(createBean) DefaultListableBeanFactory(registerBeanDefinition)
容器初始化过程
1.setParent(): 处理父容器 2.setConfigLocations(): 解析并设置xml配置文件路径 3.refresh(): 创建 beanFactory 对象并初始化, 读取 xml 配置文件得到 beanDefinitions, 接着处理两种 PostProcessor, 然后添加国际化处理器和事件广播器以及相应的初始化和一些处理, 最后实例化单例的 bean 等等. #外圈结束, 再看 refresh() 里面的每个方法 1.prepareRefresh(): 准备工作, 一些字段值的设置和处理. 2.obtainFreshBeanFactory(): 创建一个 beanFactory 对象并注册到 applicationContext (即赋值到字段上), 然后解析 xml 配置文件(或注解配置)的信息, 解析得到 beanDefinitions 并注册到容器中. 3.然后是一些对 beanFactory 对象的完善配置的代码 4.扫描并执行 BeanFactoryPostProcessor(其作用是为beanFactory对象添加东西提供扩展性), 其中我认识的就只有 ConfigurationClassPostProcessor(这个类作用就是解析 @Configuration/@Component/@Import/@ImportSource/@ComponentScan等基础注解). 5.扫描实现了 BeanPostProcessor 接口的 bean 并注册到 beanFactory 中存起来, 等 createBean 创建对象时会在对应的时机执行一些对应的方法(钩子). 常见的各种 XxxAware 就是靠这个实现的咯. 6.接着, 初始化国际化资源处理器, 事件广播器, 并注册一些需要注册的事件(也注册容器内实现对应接口的 bean) 7.处理一些 beanFactory 的配置, 接着为所有单例且非懒加载的(不就是默认策略嘛) bean 创建实例, 缓存起来. 8.广播容器加载完成了的事件. 以及处理生命周期.
最后总结下, 先创建容器, 再将根据配置文件解析得到 BeanDefinition 注册到容器中, 然后处理两大扩展(BeanFactoryPostProcessor/BeanPostProcessor), 接着是Spring的国际化, 以及相当有用的事件广播器, 最后实例化 bean. 整体感觉其实很简单, 但其实有大量的工作交给了 BeanPostProcessor.
超长源码分析过程
// 先随便写个 main 方法, 如我写的, 可测试依赖循环问题和事件监听: // 包名: cn.gudqs7.spring.tests, 改动则需同步修改xml哦 // 进入对应类代码: 快捷键 Cmd+Option+鼠标点击 (或 Ctrl+Alt+鼠标左键 ); 如果是接口松开 Option(或Alt)键 Test.java public class Test { public static void main(String[] args) { ApplicationContext xmlContext = new ClassPathXmlApplicationContext("application-wq.xml"); UserServiceImpl userService = xmlContext.getBean(UserServiceImpl.class); userService.sayHi(); } } application-wq.xml <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName"> <bean name="userService" class="cn.gudqs7.spring.tests.UserServiceImpl"> <property name="starter"><ref bean="serverStarter"/></property> </bean> <bean name="serverStarter" class="cn.gudqs7.spring.tests.ServerStarter"> <property name="userService"><ref bean="userService"/></property> </bean> </beans> UserServiceImpl.java @Service public class UserServiceImpl { @Resource private ServerStarter starter; public void sayHi() { System.out.println(starter); System.out.println("Hello Spring!"); } public void setStarter(ServerStarter starter) { this.starter = starter; } } ServerStarter.java @Service public class ServerStarter implements ApplicationListener<ContextRefreshedEvent> { @Inject private UserServiceImpl userService; @Override public void onApplicationEvent(ContextRefreshedEvent event) { String applicationName = event.getApplicationContext().getApplicationName(); System.out.println(applicationName); System.out.println(userService); System.out.println("========== started by gudqs7 =============="); System.out.println("========== started by gudqs7 =============="); System.out.println("========== started by gudqs7 =============="); } public void setUserService(UserServiceImpl userService) { this.userService = userService; } }
这篇关于Spring源码分析的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南