三. 手写简易 Spring(三)
1. Bean 对象初始化和销毁方法
1. XML 添加 init-method 与实现 InitializingBean 接口注册初始化
- 核心实现类 XmlBeanDefinitionReader:添加解析 XML 的 init-method 的参数放入 BeanDefinition 对象
- 核心抽象类 AbstractAutowireCapableBeanFactory:在调用 invokeInitMethod 方法初始化时先判断是否有 InitializingBean 初始化,再判断是否有 init-method 初始化,同时避免调用两次相同方法
2. XML 添加 destroy-method 与实现 DisposableBean 接口注册销毁
- 核心实现类 XmlBeanDefinitionReader:添加解析 XML 的 destroy-method 的参数放入 BeanDefinition 对象
- DisposableBeanAdapter 类使用了适配器的设计模式,将俩销毁方法整合在一起
- 先判断是否有 DisposableBean 销毁,再判断是否有 destroy-method 初销毁,同时避免调用两次相同方法
- 核心抽象类 AbstractAutowireCapableBeanFactory:在初始化后调用 registerDisposableBeanIfNecessary 方法
- 方法调用 DefaultSingletonBeanRegistry 类、注册带销毁的 BeanDefinition 对象
- 存在 DisposableBean 或 destroy-method 就是带销毁的 BeanDefinition 对象
- 解析 XML 与预加载单例对象后,手动注册销毁钩子时,调用 DefaultSingletonBeanRegistry 类的 destroySingletons 方法
- DefaultSingletonBeanRegistry 类存在所有销毁的 BeanDefinition 集合,依次删除、同时调用 DisposableBeanAdapter 类整合的 destroy 方法
3. DefaultSingletonBeanRegistry 优秀的解耦方法
- ConfigurableBeanFactory 接口定义了 destroySingletons 方法
- AbstractBeanFactory 实现了 ConfigurableBeanFactory 接口但自己极其子类并未实现此方法
- AbstractBeanFactory 交给了父类 DefaultSingletonBeanRegistry 实现 destroySingletons 方法,DefaultSingletonBeanRegistry 并没有实现 ConfigurableBeanFactory 接口因此无需 @Override
- 核心就是 A 继承 B实现 C 时,C 的接口方法由 A 继承的父类 B 实现
2. 定义标记类型 Aware 接口,实现感知容器对象
1. 定义
- 允许 Bean 对象拿到 Spring 框架中的 BeanFactory、BeanClassLoader、BeanName、ApplicationContext 等
- 我们可以定义 Aware 标记接口,通过 instanceof 判断
- JDK 常用标记接口:Cloneable、Serializable、RandomAccess、Remote
- 当前继承 Aware 的接口包括:BeanFactoryAware、BeanClassLoaderAware、BeanNameAware 和 ApplicationContextAware,获取对应对象
- 前三者属于 BeanFactory,因此在 beans.factory 包下
- ApplicationContextAware 属于 ApplicationContext,因此在 context 包下
- ApplicationContext 需要像容器中注册 addBeanPostProcessor ,再由 createBean 调用 applyBeanPostProcessorsBeforeInitialization 时进行操作
2. ApplicationContextAwareProcessor 包装处理器
- ApplicationContextAwareProcessor 实现 BeanPostProcessor 接口
- 在 refresh() 方法操作时,把 ApplicationContext 注册到 BeanPostProcessor 容器
- 在 createBean() 方法进行 BeanPostProcessor Before 处理时调用
3. Bean 对象作用域
1. 定义
- 是否单例存放在 BeanDefinition 中,通过 ConfigurableBeanFactory 成员变量 SCOPE_SINGLETON、SCOPE_PROTOTYPE 来定义
- 单例与否区别
- DefaultListableBeanFactory#preInstantiateSingletons 单例才预初始化
- AbstractAutowireCapableBeanFactory#createBean 创建完成对象后单例才放入到内存中
- AbstractAutowireCapableBeanFactory#registerDisposableBeanIfNecessary 注册 Disposable 销毁方法单例才执行
- 某个 Bean 对象是否单例,通过 XmlBeanDefinitionReader 解析 XML 文件校验
4. 扩展其他框架 FactoryBean
1. 定义
- Spring 对外提供一个可以二次从 FactoryBean 的 getObject 方法中获取对象的功能,这样所有实现此接口的对象类(例如其他框架),就可以扩充自己的对象功能
- MyBatis 就是实现了一个 MapperFactoryBean 类,在 getObject 方法中提供 SqlSession 执行 CRUD 方法的操作
- createBean 执行对象实例化、属性填充、依赖加载、前置后置处理、初始化等操作后,就执行 FactoryBean 具体对象中的 getObject 对象
2. FactoryBeanRegistrySupport 处理 FactoryBean 注册管理
- AbstractBeanFactory 抽象类继承 DefaultSingletonBeanRegistry 实现类,中间加一层 FactoryBeanRegistrySupport 抽象类,为了扩展出创建 BeanFactory 的能力
- AbstractBeanFactory#doGetBean 方法获取 Bean 对象时,判断是否是 FactoryBean 的子类
- 否返回当前的 Bean 对象
- 是通过 FactoryBeanRegistrySupport#getObjectFromFactoryBean 方法获取 FactorBean 对象
- FactoryBeanRegistrySupport 处理关于 FactoryBean 对象的注册管理,同时单例对象会进行缓存
- 它通过实现 FactorBean 接口,实现的 isSingleton 方法判断是否单例,实现的 getObject 方法获取 Bean 对象
6. 我的代码结构
1. 整体设计结构
2. 我的调用类图(模拟 Spring 源码)
3. 我的代码结构(模拟 Spring 源码)
.
├── beans
│ ├── BeansException.java
│ ├── PropertyValue.java
│ ├── PropertyValues.java
│ └── factory
│ ├── Aware.java
│ ├── BeanClassLoaderAware.java
│ ├── BeanFactory.java
│ ├── BeanFactoryAware.java
│ ├── BeanNameAware.java
│ ├── DisposableBean.java
│ ├── FactoryBean.java
│ ├── HierarchicalBeanFactory.java
│ ├── InitializingBean.java
│ ├── ListableBeanFactory.java
│ ├── config
│ │ ├── AutowireCapableBeanFactory.java
│ │ ├── BeanDefinition.java
│ │ ├── BeanFactoryPostProcessor.java
│ │ ├── BeanPostProcessor.java
│ │ ├── BeanReference.java
│ │ ├── ConfigurableBeanFactory.java
│ │ ├── ConfigurableListableBeanFactory.java
│ │ └── SingletonBeanRegistry.java
│ ├── support
│ │ ├── AbstractAutowireCapableBeanFactory.java
│ │ ├── AbstractBeanDefinitionReader.java
│ │ ├── AbstractBeanFactory.java
│ │ ├── BeanDefinitionReader.java
│ │ ├── BeanDefinitionRegistry.java
│ │ ├── CglibSubclassingInstantiationStrategy.java
│ │ ├── DefaultListableBeanFactory.java
│ │ ├── DefaultSingletonBeanRegistry.java
│ │ ├── DisposableBeanAdapter.java
│ │ ├── FactoryBeanRegistrySupport.java
│ │ ├── InstantiationStrategy.java
│ │ └── SimpleInstantiationStrategy.java
│ └── xml
│ └── XmlBeanDefinitionReader.java
├── context
│ ├── ApplicationContext.java
│ ├── ApplicationContextAware.java
│ ├── ConfigurableApplicationContext.java
│ └── support
│ ├── AbstractApplicationContext.java
│ ├── AbstractRefreshableApplicationContext.java
│ ├── AbstractXMLApplicationContext.java
│ ├── ApplicationContextAwareProcessor.java
│ └── ClassPathXmlApplicationContext.java
├── core
│ └── io
│ ├── ClassPathResource.java
│ ├── DefaultResourceLoader.java
│ ├── FileSystemResource.java
│ ├── Resource.java
│ ├── ResourceLoader.java
│ └── UrlResource.java
└── utils
├── ClassUtils.java
└── StringUtils.java
.
├── ApiTest.java
├── bean
│ ├── IUserDao2.java
│ ├── UserController.java
│ ├── UserDao.java
│ ├── UserService.java
│ └── UserService2.java
└── common
├── MyBean1FactoryPostProcessor.java
├── MyBean1PostProcessor.java
├── MyBean2FactoryPostProcessor.java
├── MyBean2PostProcessor.java
└── ProxyBeanFactory.java