浅尝Spring注解开发_Spring容器创建概述
lipiwang 2024-10-31 15:23 16 浏览 0 评论
概述12个方法
java
//获取ioc容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfPropertyValues.class);
java
/**
* 创建一个新的AnnotationConfigApplicationContext,派生bean定义
* 从给定的带注释的类,并自动刷新上下文。
* @param 类一个或多个带注释的类
* e.g. {@link Configuration @Configuration} classes
*/
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
java
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 为刷新准备此上下文。
prepareRefresh();
// 告诉子类刷新内部bean工厂。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备在此上下文中使用bean工厂。
prepareBeanFactory(beanFactory);
try {
// 允许在上下文子类中对bean工厂进行后处理。
postProcessBeanFactory(beanFactory);
// 调用在上下文中注册为bean的工厂处理器。
invokeBeanFactoryPostProcessors(beanFactory);
// 注册拦截bean创建的bean处理器。
registerBeanPostProcessors(beanFactory);
// 初始化此上下文的消息源。
initMessageSource();
// 为此上下文初始化事件多播。
initApplicationEventMulticaster();
// 在特定的上下文子类中初始化其他特殊bean。
onRefresh();
// 检查监听器bean并注册它们。
registerListeners();
// 实例化所有剩余的(非lazy-init)单例。
finishBeanFactoryInitialization(beanFactory);
// 最后一步:发布相应的事件。
finishRefresh();
}
//...
BeanFactory预处理
BeanFactory的创建及预准备工作
BeanFactory 的作用是负责 bean 的创建、依赖注入和初始化,bean 的各项特征由 BeanDefinition 定义BeanDefinition 作为 bean 的设计蓝图,规定了 bean 的特征,如单例多例、依赖关系、初始销毁方法等BeanDefinition 的来源有多种多样,可以是通过 xml 获得、配置类获得、组件扫描获得,也可以是编程添加所有的 BeanDefinition 会存入 BeanFactory 中的 beanDefinitionMap 集合
1、this()
- 先调用父类构造器
- 声明两个类,通过读取注解或者扫描类路径读取BeanDefinition
- 初始化了DefaultListableBeanFactory:基于bean定义元数据的成熟bean工厂,可通过后处理器进行扩展,内部定义了 BeanDefinition的Map属性名beanDefinitionMap,可以操作bean
- 注册了多个(6个)默认的后置处理器
2、register(annotatedClasses)
- 校验传入的 JavaConfig.class配置类的注解(是否需要忽略)
- 处理通用注解
- 封装为BeanDefinitionHolder后,注册到容器中
- 相当于将JavaConfig配置类作为一个Bean注册到容器中
3、Spring容器的refresh():创建刷新
- prepareRefresh():刷新前的预处理initPropertySources()[初始化属性源]:初始化一些属性设置,空方法,留给子类自定义个性化的属性设置方法getEnvironment().validateRequiredProperties():检验属性的合法等earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>():保存容器中的一些早期的事件,一旦多播机可用就会发布
- obtainFreshBeanFactory()(//告诉子类刷新内部Bean工厂):获取新鲜的BeanFactoryConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()类注释://大多数可列出的bean工厂要实现的配置接口。 除了 {@link ConfigurableBeanFactory} 之外,它还提供了以下工具: 分析和修改 bean 定义,并预实例化单例。refreshBeanFactory():刷新
[创建]BeanFactory创建了一个this.beanFactory = new DefaultListableBeanFactory()。补充:这个方法在创建AnnotationConfigApplicationContext的父类GenericApplicationContext的无参构造时调用了,注释是//创建一个新的 GenericApplicationContext设置idgetBeanFactory():返回刚才GenericApplicationContext创建的BeanFactory对象将创建的BeanFactory[类型:DefaultListableBeanFactory]返回 - prepareBeanFactory(beanFactory):BeanFactory的预准备工作(BeanFactory进行一些设置)设置BeanFactory的类加载器、支持表达式解析器...添加部分BeanPostProcessor[类型:ApplicationContextAwareProcessor]设置忽略的自动装配的接口EnvironmentAware、EmbeddedValueResolverAware、xxx...注册可以解析的自动装配;我们能直接在任何组件中自动注入:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext...添加BeanPostProcessor[类型:ApplicationListenerDetector],将用于检测内部 bean 的早期后处理器注册号为 ApplicationListener添加编译时的AspectJ给BeanFactory中注册一些能用的组件;ConfigurableEnvironment environment: application上下文环境Map<String, Object> systemProperties:系统属性Map<String, Object> systemEnvironment:系统环境变量
- postProcessBeanFactory(beanFactory):BeanFactory准备工作完成后进行的后置处理工作子类通过重写这个方法来在BeanFactory创建并预准备完成以后做进一步的设置
执行BeanFactoryPostProcessor
BeanFactoryPostProcessor是beanFactory的后置处理器
BeanFactoryPostProcessor是beanFactory的后置处理器,在BeanFactory标准初始化之后调用,来定制和修改BeanFactory的内容,所有的bean定义已经保存加载到beanFactory,但是bean的实例还未创建
执行BeanFactoryPostProcessor分两步,先执行BeanDefinitionRegistryPostProcessor,后执行BeanFactoryPostProcessor
- invokeBeanFactoryPostProcessors(beanFactory):执行BeanFactoryPostProcessor的方法。BeanFactoryPostProcessor:BeanFactory的后置处理器。在BeanFactory标准初始化(以上4步)之后执行的,两个接口:BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor
- 执行BeanFactoryPostProcessor的方法
- 先执行BeanDefinitionRegistryPostProcessor
- 获取所有的BeanDefinitionRegistryPostProcessor
- 看先执行实现了PriorityOrdered优先级接口的BeanDefinitionRegistryPostProcessor
- postProcessor.postProcessBeanDefinitionRegistry(registry)
- 再执行实现了Ordered顺序接口的BeanDefinitionRegistryPostProcessor
- postProcessor.postProcessBeanDefinitionRegistry(registry)
- 最后执行没有实现任何优先级或者是顺序接口的BeanDefinitionRegistryPostProcessors
- postProcessor.postProcessBeanDefinitionRegistry(registry)
- 再执行BeanFactoryPostProcessor的方法
- 获取所有的BeanFactoryPostProcessor
- 看先执行实现了PriorityOrdered优先级接口的BeanFactoryPostProcessor
- postProcessor.postProcessBeanFactory()
- 再执行实现了Ordered顺序接口的BeanFactoryPostProcessor
- postProcessor.postProcessBeanFactory()
- 最后执行没有实现任何优先级或者是顺序接口的BeanFactoryPostProcessor
- postProcessor.postProcessBeanFactory()
注册BeanPostProcessor
按照优先级注册后置处理器,不执行
- registerBeanPostProcessors(beanFactory):注册BeanPostProcessor(Bean的后置处理器)拦截Bean的创建
- 不同接口类型的BeanPostProcessor,在Bean创建前后的执行时机是不一样的
- BeanPostProcessor后置处理器
- DestructionAwareBeanPostProcessor销毁感知后置处理器
- InstantiationAwareBeanPostProcessor实例化感知后置处理器
- SmartInstantiationAwareBeanPostProcessor智能实例化感知后置处理器
- MergedBeanDefinitionPostProcessor[internalPostProcessors]合并Bean定义信息后置处理器
- 获取所有的BeanPostProcessor,后置处理器都默认可以通过PriorityOrdered、Ordered接口来执行优先级
- 先注册PriorityOrdered优先级接口的BeanPostProcessor
- 把每一个BeanPostProcessor添加到BeanFactory中,beanFactory.addBeanPostProcessor(postProcessor)
- 再注册Ordered接口的
- 最后注册没有实现任何优先级接口的
- 最终注册MergedBeanDefinitionPostProcessor
- 注册一个ApplicationListenerDetector,来在Bean创建完成后检查是否是ApplicationListener,如果是就添加组件applicationContext.addApplicationListener((ApplicationListener<?>) bean)
初始化MessageSource
国际化
- initMessageSource():初始化MessageSource组件(做国际化功能;消息绑定,消息解析)
- 获取BeanFactory
- 看容器中是否有id为messageSource的,类型是MessageSource的组件,如果有赋值给messageSource,如果没有自己创建一个DelegatingMessageSource
- MessageSource:取出国际化配置文件中的某个key的值;能按照区域信息获取
- 把创建好的MessageSource注册在容器中,以后获取国际化配置文件的值的时候,可以自动注入MessageSource
- beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource)
- MessageSource.getMessage(String code, Object[] args, String defaultMessage, Locale locale)
初始化事件派发器、监听器
- initApplicationEventMulticaster():初始化事件派发器
- 获取BeanFactory
- 从BeanFactory中获取applicationEventMulticaster的ApplicationEventMulticaster
- 如果上一步没有配置,就创建一个SimpleApplicationEventMulticaster
- 将创建的ApplicationEventMulticaster添加到BeanFactory中,以后其他组件直接自动注入
- onRefresh():留给子容器(子类)
- 子类重写这个方法,在容器刷新的时候可以自定义逻辑;
- registerListeners():给容器中将所有项目里面的ApplicationListener注册进来;
- 从容器中拿到所有的ApplicationListener
- 将每个监听器添加到事件派发器中
- getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName)
- 派发之前步骤产生的事件
创建Bean准备、完成
有代理对象就用,没有就创建,然后在初始化前后准备各种后置处理器,创建完成后放入各种Map
- finishBeanFactoryInitialization(beanFactory):初始化所有剩下的单实例bean
- beanFactory.preInstantiateSingletons():初始化剩下的单实例bean
- 获取容器中的所有Bean,依次进行初始化和创建对象
- 获取Bean的定义信息:RootBeanDefinition
- 判断Bean不是抽象的,是单实例的,不是懒加载
- 判断是否是FactoryBean,是否是实现FactoryBean接口的Bean
- 如果不是工厂Bean。利用getBean(beanName):创建对象
- 这个getBean(beanName)就是平时测试类中用到的ioc.getBean()
- doGetBean(name, null, null, false)
- 先获取缓存中保存的单实例Bean。this.singletonObjects.get(beanName),如果能获取到说明这个Bean之前被创建过(所有创建过的单实例Bean都会被缓存起来)
- 可以从private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256)属性获取到
- 缓存中获取不到,开始Bean的创建对象流程,使用BeanFactory
- 标记当前bean已经被创建markBeanAsCreated(beanName)
- 获取Bean的定义信息
- 【获取当前Bean依赖的其他Bean,mbd.getDependsOn(),如果有按照就getBean()把依赖的Bean先创建出来】
- 启动单实例Bean的创建流程
- 进入匿名类的createBean(beanName, mbd, args)方法(可以打断点进入)
- Object bean = resolveBeforeInstantiation(beanName, mbdToUse)[给 BeanPostProcessors 一个返回代理而不是目标 Bean 实例的机会]:让BeanPostProcessor先拦截返回代理对象
- 【InstantiationAwareBeanPostProcessor提前执行,就是在AOP中先于BeanPostProcessor执行的那个组件】
- 先触发:postProcessBeforeInstantiation()实例化前的后处理
- 如果有返回值,触发:postProcessAfterInitialization()初始化后的后处理
- 如果前面的InstantiationAwareBeanPostProcessor没有返回代理对象,调用第4步创建Bean
- Object beanInstance = doCreateBean(beanName, mbdToUse, args):创建Bean
- 【创建Bean实例】:createBeanInstance(beanName, mbd, args)
- 利用工厂方法或者对象的构造器创建出Bean实例
- applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)[允许后处理器修改合并的 Bean 定义。]
- 调用MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition(mbd, beanType, beanName)
- 【Bean属性赋值】populateBean(beanName, mbd, instanceWrapper)
- 赋值之前:
- 拿到InstantiationAwareBeanPostProcessor后置处理器:
- postProcessAfterInstantiation()实例化后的后处理(对应上面(8.2))
- 拿到InstantiationAwareBeanPostProcessor后置处理器:
- ibp.postProcessPropertyValues()后处理属性值
- 开始赋值:
- 应用Bean属性的值;为属性利用setter方法等进行赋值:
- applyPropertyValues(beanName, mbd, bw, pvs)
- 【Bean初始化】initializeBean(beanName, exposedObject, mbd):
- 【执行Aware接口方法】invokeAwareMethods(beanName, bean):执行xxxAware接口的方法,如BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
- 【在初始化之前应用 BeanPostProcessors】applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)
- BeanPostProcessor.postProcessBeforeInitialization()
- 【执行初始化方法】invokeInitMethods(beanName, wrappedBean, mbd)
- 是否是InitializingBean接口的实现;执行接口规定的初始化
- 是否自定义初始化方法
- 【在初始化之后应用 BeanPostProcessors】applyBeanPostProcessorsAfterInitialization
- BeanPostProcessor.postProcessAfterInitialization()
- 注册Bean的销毁方法
- 将创建的Bean添加到缓存中singletonObjects
ioc容器就是这些Map,很多的Map里面保存了单实例Bean,环境信息...
所有Bean都利用getBean创建完成以后:检查所有的Bean是否是SmartInitializingSingleton[智能初始化单例]接口的,如果是,就执行afterSingletonsInstantiated()在单例实例化之后
容器创建完成
- finishRefresh():完成BeanFactory的初始化创建工作,IOC容器就创建完成
- initLifecycleProcessor():初始化和生命周期有关的后置处理器:LifecycleProcessor
- 默认从容器中找是否有lifecycleProcessor的组件【LifecycleProcessor】;
- 如果没有new DefaultLifecycleProcessor();
- 加入到容器onRefresh()
- 写一个LifecycleProcessor的实现类,可以在BeanFactory的生命周期onRefresh()、onClose()处拦截
- getLifecycleProcessor().onRefresh()
- 拿到前面定义的生命周期处理器(BeanFactory),回调onRefresh()
- publishEvent(new ContextRefreshedEvent(this)):发布容器刷新完成事件
- LiveBeansView.registerApplicationContext(this)
如果本文对你有帮助,别忘记给我个3连 ,点赞,转发,评论,,咱们下期见。
收藏 等于白嫖,点赞才是真情。
原文作者: 蔚然丶丶
相关推荐
- 一个简单便捷搭建个人知识库的开源项目(MDwiki)
-
这里我通过自动翻译软件,搬运总结MDwiki官网的部署和使用方法。第一步:下载编译好的后MDwiki文件,只有一个HTML文件“mdwiki.html”。第二步:在mdwiki.html同级目录创建“...
- 强大、简洁、快速、持续更新 PandaWiki新一代 AI 驱动的开源知识库
-
PandaWiki是什么PandaWiki是一款AI大模型驱动的开源知识库搭建系统,帮助你快速构建智能化的产品文档、技术文档、FAQ、博客系统,借助大模型的力量为你提供AI创作、AI问答...
- DeepWiki-Open: 开源版Deepwiki,可自己构建github文档库
-
Deepwiki是Devin团队开发的github文档库,用户能免费使用,但代码不是开源,而DeepWiki-Open侧是开源版本的实现。DeepWiki-Open旨在为GitHub和GitLa...
- 最近爆火的wiki知识管理开源项目PandaWiki
-
项目介绍PandaWiki是一款AI大模型驱动的开源知识库搭建系统,帮助你快速构建智能化的产品文档、技术文档、FAQ、博客系统,借助大模型的力量为你提供AI创作、AI问答、AI搜索等...
- 轻量级开源wiki系统介绍(轻量开源论坛系统)
-
wiki系统有很多DokuWiki、MediaWiki、MinDoc等等都是开源的wiki系统。商业版的wiki,像很多企业在用的confluence等。今天我们讲的是一款轻量级且开源的文档管理系统:...
- DNS解析错误要怎么处理(dns解析状态异常怎么办)
-
在互联网时代,网络已经成为人们生活和工作中不可或缺的一部分。然而,当遇到DNS解析错误时,原本畅通无阻的网络访问会突然陷入困境,让人感到十分困扰。DNS,即域名系统,它如同互联网的电话簿,将人们易于...
- 网页加载慢?这些方法让你秒开网页!
-
打开浏览器,信心满满地准备查资料、看视频或者追剧,却发现网页怎么都打不开!是不是瞬间感觉手足无措?别慌,这个问题其实挺常见,而且解决起来并没有你想象的那么复杂。今天就来聊聊网页打不开究竟是怎么回事,以...
- windows11 常用CMD命令大全(windows11msdn)
-
Windows11中的命令提示符(CMD)是一个强大的工具,可以通过命令行执行各种系统操作和管理任务。以下是一些常用的CMD命令,按功能分类整理,供你参考:一、系统信息与状态systeminfo显...
- 电脑提示DNS服务器未响应怎么解决?
-
我们在使用电脑的时候经常会遇到各种各样的网络问题,例如最近就有Win11电脑用户在使用的时候遇到了DNS未响应的问题,遇到这种情况我们应该怎么解决呢? 方法一:刷新DNS缓存 1、打开运行(W...
- 宽带拨号错误 651 全解析:故障定位与修复方案
-
在使用PPPoE拨号连接互联网时,错误651提示「调制解调器或其他连接设备报告错误」,通常表明从用户终端到运营商机房的链路中存在异常。以下从硬件、系统、网络三层维度展开排查:一、故障成因分类图...
- 如何正确清除 DNS 缓存吗?(解决你访问延时 )
-
DNS缓存是一个临时数据库,用于存储有关以前的DNS查找的信息。换句话说,每当你访问网站时,你的操作系统和网络浏览器都会保留该域和相应IP地址的记录。这消除了对远程DNS服务器重复查询的...
- 网络配置命令:ipconfig和ifconfig,两者有啥区别?
-
在计算机网络的世界里,网络接口就像是连接你电脑和外部网络的桥梁,而网络配置则是确保这座桥梁稳固、通信顺畅的关键。提到网络配置工具,ipconfig和ifconfig绝对是两个绕不开的名字。它们一...
- 救急的命令 你会几个?(救急一下)
-
很多人都说小编是注册表狂魔,其实不完全是,小编常用的命令行才是重点。其实所谓的命令行都是当初DOS时代的标准操作方式,随着Windows不断演化,DOS的命令早已成为Windows的一部分了——开始菜...
- 电脑有网却访问不了GitHub原来是这样
-
当满心欢喜打开电脑,准备在GitHub这个“开源宝藏库”里挖掘点超酷的项目,却遭遇了网页无法访问的尴尬。看着屏幕上那令人无奈的提示,原本高涨的热情瞬间被泼了一盆冷水,是不是感觉世界都不美好了...
- rockstargames更新慢| r星更新速度 怎么办 解决办法
-
rockstargames更新慢|r星更新速度怎么办解决办法说到RockstarGames,那可是游戏界的大佬,作品个顶个的经典。但话说回来,每当新内容更新时,那蜗牛般的下载速度,真是让人急得...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- maven镜像 (69)
- undefined reference to (60)
- zip格式 (63)
- oracle over (62)
- date_format函数用法 (67)
- 在线代理服务器 (60)
- shell 字符串比较 (74)
- x509证书 (61)
- localhost (65)
- java.awt.headless (66)
- syn_sent (64)
- settings.xml (59)
- 弹出窗口 (56)
- applicationcontextaware (72)
- my.cnf (73)
- httpsession (62)
- pkcs7 (62)
- session cookie (63)
- java 生成uuid (58)
- could not initialize class (58)
- beanpropertyrowmapper (58)
- word空格下划线不显示 (73)
- jar文件 (60)
- jsp内置对象 (58)
- makefile编写规则 (58)