Spring容器设计
2021-10-08 15:51:53 0 举报
自己写一个 Spring, 其对应的功能逻辑; - 从BeanDefinition - 对象实例化 - 注入属性与依赖 - Xml配置资源加载 - (BeanFactory + Xml配置资源加载) => 上下文 - 初始化与销毁方法 - Aware 感知容器 - 单例与原型(作用域) + FactoryBean - 事件与监听
作者其他创作
大纲/内容
getBean(beanName)
applyBeanPostProcessorsBeforeInitialization
applicationEventMulticaster.multicastEvent(event);
1. 修改BeanDefinition的信息2. 注册 beanPostProcessors对象
创建Bean
createBean
applyBeanPostProcessorsAfterInitialization
BeanFactoryPostProcessors
SimpleApplicationEventMulticaster
2. 获取Bean定义
创建事件发布者 publish
构建Bean工厂
Class beanClass;类对象
一般是Spring容器关闭时候,才会执行DisposableBean的destory方法
N
事件
事件发布者 EventMulticaster放置到单例注册表中
initMethoddestoryMethod方法名
InvokeInitMethods
BeanFactory
初始化 initialBean
SimpleApplicationEventMulticaster.multicastEvent(event)
XmlBeanDefinitionReader配置文件加载
事件触发流程
注册事件监听器
3. Bean 放置到单例注册表中
增加 Aware 接口,让 Spring Bean 可以感知到容器
属性填充
那么,如果我们想获得Spring框架提供的BeanFactory、ApplicationContext、BeanClassLoader等这些能力做一些扩展框架的使用时该怎么操作呢。所以我们本章节希望在 Spring框架中提供一种能感知容器操作
Start
具体发布者(被观察者)
反射..
存在于单例注册表中
观察者模式讲解:https://zhuanlan.zhihu.com/p/158537313
if( bean instanceof FactoryBean )
registerBeanPostProcessors(beanFactory)
使用fBean= factoryBean.getObject()生成对应的对象
创建Bean对象
Bean 放置到单例注册表中
Y
BeanDefinition
注册
Spring 内部的对象Xml配置的对象,比如:UserDao、UserService、UserController
调用对应的实例化策略
将 BeanFactory、BeanName、 类加载器等信息放入到Bean中
监听器中的观察者模式
PropertyValues propertyValues;属性集合
...
1. 查看单例注册表中是否存在对象
1. 从功能上看Small Spring 框架构建流程
1. 如何感知到 Spring 容器2. 用到 ApplicationContext、 BeanClassLoader等能力
监听器2(具体观察者)
4. 返回 Bean 对象
1. BeanDefinition 属性的增加2. initMethod方法的实现3. DisposableBean的相关实现(Map容器,DisposableBean方法)
ApplicationEventMulticaster
返回Bean
1. 创建 BeanFactory2. 读取Xml配置3. 进行 BeanDefinition的注册
1. JDK2. Cglib
BeanDeifinition
Runtime.getRuntime().addShutdownHook(new Thread(this::close));
注册DisposableBean 到对应Map中
核心的getBean方法其获取Bean的流程
ClassPathXmlApplicationContext
finishRefresh
invokeBeanFactoryPostProcessors(beanFactory);
Spring启动时候就会将 BeanDefinition 注册到Map中
InvokeInitMethods 在xml文件中需要配置对应方法
提前实例化单例Bean对象
1. 创建 BeanFactory2. 读取 Xml 配置3. 进行 BeanDefinition的注册
对于一些外部的包,比如 MyBatis 的某一个 Bean,在我们实现的Spring框架中想要使用该Bean,则需要实现对应的 FactoryBean 接口,如下:public interface FactoryBean<T> { T getObject() throws Exception; Class<?> getObjectType(); boolean isSingleton();}然后在getBean方法中会就生成的 bean 进行判断,判断是否是 FactoryBean 的实例;若是,则通过该 bean 对象的getObject() 方法创建 xxxBean;注意:最后的 xxxBean 才是我们需要的 MyBatis 对象, factoryBean 是我们产生该对象的工具。
注册到单例注册表
SCOPE_SINGLETONSCOPE_PROTOTYPEscope 作用域
BeanName
FactoryBean 放置到对应Map容器中中
public void multicastEvent(final ApplicationEvent event) { for (final ApplicationListener listener : getApplicationListeners(event)) { listener.onApplicationEvent(event); } }
1. 构建事件发布者2. 并且注册到单例注册表中
在单例注册表中不存在
触发
每个DisposableBean都存在对应的destory方法
初始化与销毁方法
<?xml version=\"1.0\" encoding=\"UTF-8\"?><beans> <bean id=\"userDao\" class=\"bean.UserDao\"/> <bean id=\"userService\" class=\"bean.UserService\"> <property name=\"uId\" value=\"10001\"/> <property name=\"userDao\" ref=\"userDao\"/> </bean> ...</beans>
preInstantiateSingletons
监听器列表
事件发布者发布事件
让监听器执行对应方法
调用
ApplicationEvent
ApplicationListener
从单例注册表中获取Listener类型的Bean
1. 存放 BeanDefinition 的 Map,key是类名(字符串),value是 beanDefinition2. 存放单例 Bean 的 Map,key是类名(字符串),value是单例 Bean 对象
2. 具体编码是怎么实现的?
Xml配置 + BeanFactory
是否单例
<beans> <bean id=\"userDao\" class=\"cn.bugstack.springframework.test.bean.UserDao\" init-method=\"initDataMethod\" destroy-method=\"destroyDataMethod\"/> <bean id=\"userService\" class=\"cn.bugstack.springframework.test.bean.UserService\"> <property name=\"uId\" value=\"10001\"/> <property name=\"company\" value=\"腾讯\"/> <property name=\"location\" value=\"深圳\"/> <property name=\"userDao\" ref=\"userDao\"/> </bean> <bean class=\"cn.alvin.springframework.test.common.MyBeanPostProcessor\"/> <bean class=\"cn.alvin.springframework.test.common.MyBeanFactoryPostProcessor\"/></beans>
DisposableBean
资源加载
完成refresh,执行对应的监听器方法
Aware 感知容器对象
registerListeners
1. BeanDefinition中新增两个属性:2. 对应的读取Xml配置的时候,需要增加scope信息的解析3. 创建 与 销毁的时候需要判断是否是原型或单例
Object
<beans> <bean id=\"userDao\" class=\"cn.alvin.springframework.test.bean.UserDao\"/> <bean id=\"userService\" class=\"cn.alvin.springframework.test.bean.UserService\"> <property name=\"uId\" value=\"10001\"/> <property name=\"company\" value=\"华为\"/> <property name=\"location\" value=\"深圳\"/> <property name=\"userDao\" ref=\"userDao\"/> </bean> <bean class=\"cn.alvin.springframework.test.common.MyBeanPostProcessor\"/> <bean class=\"cn.alvin.springframework.test.common.MyBeanFactoryPostProcessor\"/></beans>
Xml文件解析
调用getBean为每一个BeanDefinition创建单例
Xml配置中 增加 init-Method 和 destory-Method两个配置属性
return
1. 事件2. 监听器3. 事件发布者的注册、监听器的注册3. 观察者模式4. 事件触发流程
bean instanceof Aware
调用BeanFactory的 注册功能模块,进行BeanDefinition的注册
核心的getBean方法其获取Bean的流程createBean() 需要对应的实例化策略,并考虑属性的填充(基本数据类型、引用数据类型)
destory() 方法
新增:对Bean处理的PostProcess机制!Bean的初始化方法!
将所有 Listener 对应的Bean 注册到监听器集合
public void close() { getBeanFactory().destroySingletons(); }
1. Scope :Bean 的作用域
触发事件
Set<ApplicationListener<Event>>监听器集合
PostProcess1. BeanDefinition的定义信息修改2. Bean的实例化信息扩展3. XmlBeanDefinitionReader + BeanFactory => ClassPathXmlApplicationContext
容器完成refresh之后执行
增加 Xml 配置,将BeanDefinition的配置信息放置在Xml配置文件中
从单例注册表中获取Bean
事件发布者(被观察者)
initApplicationEventMulticaster
增加监听器
监听器1(具体观察者)
2. FactoryBean 注册服务
获取 event 对应的监听器
MyBatis...之类的外部包
该fBean是否单例
判断对应的Bean对象是否是 FactoryBean
监听器(抽象观察者)
0 条评论
下一页