最新要闻
- IPX6级防水防刮:宏碁墨尔本背包169元抄底(三种款式)
- 焦点快播:博主发薅高铁商务座羊毛攻略 20元享超VIP服务网友效仿:12306回应怒赞
- 环球快消息!平台回应机票一分钟三次变价:实时价格变动正常
- 英雄之光|陈旧的记录本 是他牵挂群众最温暖的见证
- 世界即时看!你的工资不能低于这数!31省份最低工资公布:时薪达标没
- 世界最资讯丨山东推出399元高铁环游套票:有效期5天、全省免费换乘
- 每日热议!DIY万能钥匙!主板检测灯你不得不懂
- 【焦点热闻】09款奥迪A4L标准型改装泪眼/导航作业
- 世界速看:全新深红配色亮相!iPhone 15 Pro超高清外观渲染图首曝:钛金属边框、Type-C接口
- 世界资讯:诈骗网红梅尼耶的MCN游良文化被申请破产:小刚学长等多位网红受骗
- 动态:大学招聘体育老师 要求得过奥运冠军引热议:官方回应专业技能很重要
- 复星旅文2022年收入137.78亿元 徐晓亮:要尽快追回过去三年失去的业绩
- 女主不够性感吗?《生化危机4重制版》发售两周狂卖超400万份:Steam好评如潮
- Intel中国特供i5-13490F/i7-13790F闪电降价:性价比更神了!
- 天天看热讯:男人多次失恋后和娃娃订婚 还“生”了三个孩子
- 当年找抖音赔30亿的腾讯视频 这会儿怎么来世纪大和解了?
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
环球观热点:《系列一》-- 4、xml配置文件解析之[默认]命名空间[标签]的解析
阅读之前要注意的东西:本文就是主打流水账式的源码阅读,主导的是一个参考,主要内容需要看官自己去源码中验证。全系列文章基于 spring 源码 5.x 版本。
Spring源码阅读系列--全局目录.md
引子
【资料图】
1、容器最基本使用.md
系列1 - bean 标签解析:
2、XmlBeanFactory 的类图介绍.md
3、XmlBeanFactory 对xml文件读取.md
4、xml配置文件解析之【默认】命名空间【标签】的解析.md
5、xml配置文件解析之【自定义】命名空间【标签】的解析.md
系列2 - bean 获取: getBean() 做了什么
前言
一句话概括:
- 读取 xml 文件中硬编码的各种标签,解析为spring 容器可以识别的形式,并注册到:BeanFactory 中 (BeanDefinitionRegistry)
【只读取配置内容,并注册管理】
1 前文回顾
书接上回,上文终止余如下图所示的位置:
2 bean.xml 实例
既然要真刀真枪的将 xml 文件的标签解析了,那么我们不能继续无实物表演了,下边的例子是从spring 5.x 源码里随机找打的一个 xml 案例:
上述作为案例的:beanEvents.xml 文件中包含了,我们在 "默认命名空间" 下所关注的四种标签都有,用来做本文的案例简直再完美不过了。
先来个简单的介绍:
beans:
- 一个beans 包含0到多个 bean、0到多个 import、0到多个 alias,所以对beans 的解析会最终变成对如下几个标签的递归解析
alias:
- bean的别名定义,这个应该是这几个标签最简单的了
bean:
- 这个标签是本文绝对的主角,也是spring系列里的核心角色
- bean 标签,拥有但是不局限于下图所示的直接属性
- 所谓直接属性就是 这种可直接配置的
- 就算不认识全部,总有眼熟的吧?平时写的注解是不是有出现在下图呢? 至于用途就不再赘述了
import:
从给出的xml文件案例里也能看出,import就是导入了一个外部定义的 "bean.xml"。
对它的解析会变成对这个外部引入的 "bean.xml" 的递归解析。
3 spring 默认命名空间解析:parseDefaultElement
接下来进入 parseDefaultElement 方法内部,见下图:
方法代码的4个分支,代表的就是 4 中默认命名空间标签的解析,这里重点关注的只有最重要的: bean 标签。
4 关于 bean 标签的解析 processBeanDefinition
这里用红色裱起来了,就说明又到了:关键的代码简单,事情不简单环节了。
4.1 标记的第一行:
委托 BeanDefinitionDelegate 类对象,解析 bean 标签的上的属性。
返回值类型:BeanDefinitionHolder 顾名思义,可以把它看作一个 bean 标签配置的相关属性的容器,至于是哪些属性,后续展开。
4.2 标记第二行:
- 当 bean 标签下边还存在:非spring 官方的支持的,用户自己魔改标签时,需要经过第二行代码,再进行了一轮自定义标签的解析。【不是本文重点关注的内容】
- 如下所示, bean 标签下又有了 mybean 标签,这个一看就不是spring 官方的原装货,所以它需要被单独解析,自定义标签的解析动作被委托给了:
- delegate.decorateBeanDefinitionIfRequired()
4.3 标记第三行
- xml 配置解析结束,解析结果需要注册到:XmlBeanFactory
4.4 标记第四行
- 代表解析动作结束了,这里触发一个响应事件,告知相关的监听器,这个 bean 已经加载成功了。
本章前边提到的四行代码会对应后续的: 【第5 ~ 第8 章】
如果后边忘记了,可以回过头来看看。
5 bean 标签默认属性的解析
本节对应的是 4.1 所标注的那一行代码
这里实际上还没进入正题:
- 简单的处理下id、name、别名
- 重点是 标注出来的那一行代码
- 上图中,标注的这行代码之后的内容也挺简单的,就是判断 beanName 若为空将按照一定规则自动生成,就像你用了 @Bean @Service @Compement 等等注解,但是没有指定 name那样,容器会自动生成 beanName
下边说回正题:
- 看下图中标记的三块代码,它们代表着 [第五章] 的3个小节
5.1 上图标注的第一部分:解析结果的承载者的初始化
上图中,依稀可见这么一行代码:AbstractBeanDefinition bd = createBeanDefinition(className, parent);
这里创建的 BeanDefinition 对象,就是用来承载,我们bean的配置内容解析结果的。
就像你配置的 xml对象,你自己能直接读懂,但是要让 spring 容器去读它时,spring容器会将这个 xml 文本内容进行翻译, 而bd [BeanDefinition] 承载的就是翻译结果。
顺着createBeanDefinition() 方法进去,最终会发现 bd的类型固定是: GenericBeanDefinition,下边是它的类图:
我们还记得 XmlBeanFactory 有个重要的接口:
- BeanDefinitionRegistry ,它管理的就是:BeanDefinition。
- 实际上,BeanDefinitionRegistry 就是以map 的形式,对spring 的配置信息
进行保存的。
PS 而到目前为止,我们的所有篇幅都在介绍 这个翻译过程, 且还没介绍完。
至于为什么敢说它承载了 xml的翻译结果,请看下图所示的 AbstractBeanDefinition 类的所有成员变量,请问是不是很眼熟呢?
拓展讲点东西,AbstractBeanDefinition 实际上有三个子类:
已知 xml 中可以定义: 父/子bean的关系
- RootBeanDefinition:早期版本中,若 bean 没有父bean 则用 RootBeanDefinition
- ChildBeanDefinition: 早期版本中用于,若 bean 定义了父bean 则用 ChildBeanDefinition 承载 bean 配置属性
- GenericBeanDefinition:他是spring 2.5 版本后提供的一站式 BeanDefinition 服务类
- 我们从 当前的spring 5.x 版本的源码中对这个问题,就可以窥见一些东西。你看上述的 createBeanDefinition() 方法,内部 bd 的实例化就一个选择:GenericBeanDefinition。
瞅瞅:父子bean的例子
5.2 标注的第二部分:bean标签硬编码的 [直接]属性解析
被标注的代码
// 硬编码解析默认的bean属性 所有元素 "属性" 解析parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
详情:
/** * Apply the attributes of the given bean element to the given bean * definition. * @param ele bean declaration element * @param beanName bean name * @param containingBean containing bean definition * @return a bean definition initialized according to the bean element attributes */public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,@Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {// 是否单例if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {error("Old 1.x "singleton" attribute in use - upgrade to "scope" declaration", ele);}// 作用范围 public class ? else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));}else if (containingBean != null) {// Take default from containing bean in case of an inner bean definition.bd.setScope(containingBean.getScope());}// 是否抽象abstract if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));}// 懒加载 属性 延迟加载String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);if (isDefaultValue(lazyInit)) {lazyInit = this.defaults.getLazyInit();}bd.setLazyInit(TRUE_VALUE.equals(lazyInit));// 是否 autowrie 自动装配String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);bd.setAutowireMode(getAutowireMode(autowire));// depends-on 依赖 属性 依赖检查 spring 3.0 以后弃用if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));}// 自动装配条件、前提 属性 值为 false 时,该bean不会被作为其他bean自动自动装配的候选者,// 但是它自身自动装配时,可以使用别的bean作为它自己的候选者String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);if (isDefaultValue(autowireCandidate)) {String candidatePattern = this.defaults.getAutowireCandidates();if (candidatePattern != null) {String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));}}else {bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));}// primary 属性 (初级、初始) if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));}// 初始化方法 属性。。。if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);bd.setInitMethodName(initMethodName);}else if (this.defaults.getInitMethod() != null) {bd.setInitMethodName(this.defaults.getInitMethod());bd.setEnforceInitMethod(false);}// 注销、关闭方法 属性if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);bd.setDestroyMethodName(destroyMethodName);}else if (this.defaults.getDestroyMethod() != null) {bd.setDestroyMethodName(this.defaults.getDestroyMethod());bd.setEnforceDestroyMethod(false);}if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) { // factory-method 属性bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));}if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) { // factory-bean 属性bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));}return bd;}
5.3 标注的第三块代码:bean标签 - 子标签属性解析
我们重新把那张图请回来:
看原谅色的注解
5.3.1 子标签属性用法介绍
1)、 meta:
元数据, 看图中案例,就是些键值对形式配置的数据;元数据并非 bean 配置的 class 的属性,它是一个额外的声明;需要使用时,通过 BeanDefinition 的 getAttribute(key) 方法获取。
2)、 lookup-method:
这个属性用得实际是使用比较少,看下边的案例:
id="lookUpTest" 的bean配置的 class是抽象类:LookUpTest.java(理论上来说抽象类是不能被实例化的)。
但是按下边的方法配置后,你会发现:
当你通过容器调用如下代码:并不会报错:
LookUpTest obj = (LookUpTest) new XmlBeanFactory("lookUpTest.xml").getBean("lookUpTest")
obj.execute();
这里execute() 内部的抽象方法 getUser() 会获取到xml 中配置的id="userBean"的 java.User对象
如果你了解设计模式,就知道这里的妙用了
- 如果是策略模式:我们可以通过xml配置文件,动态决定注入何种算法。
3)、 replaced-method:
上一节提到的 lookup-method 动态替换抽象方法返回的bean;
而replaced-method 动态替换 已经实现的方法逻辑;
看看上图的案例:它会把 executeBean 的 doSomething() 方法的逻辑替换为:doSomethingReplacer中重写的方法逻辑
但是它有个要求:被用来替换的,doSomethingReplacer所属的类必须实现如下接口
- 最终 doSomething 方法的逻辑将会被替换为:reimplement() 方法所执行的逻辑
4)、 constructor:
- 如上图所示,顾名思义,其作用就是将另一个bean配置为当前bean构造函数的入参
property:
图一出,就不用介绍干啥用的了吧?
qualifier:
至于它,就更简单了,可以认为它是,我们在给bean注入属性的时候,指定过滤条件
- 【spring 要求通过同样的beanName,只能匹配到一个满足条件的bean,否则容器将会报错】。
- 回忆下,我们通过注解使用 @Qualifier,其实就是在设置过滤,spring 需要保证,最终满足 qualifier 条件条件的bean只能有一个:
@Qualifier("integerRepo")private Repository> integerRepositoryQualifierProvider;
qualifier,甚至还支持通过属性进行过滤:
- 假如我们将多个 UserBean 注入了容器,qualifier 支持通过 UserBean的属性进行过滤
如下所示 的是 qualifier 的三种配置方式:
下图是 qualifier 的一般使用场景:
- dataSource 和 dataSource2 明显是同类型的不同bean
- 假如 location 配置 sql不同时,它们就不能随意混用了
- 所以可以通过 beanName 不同这一点进行过滤
5.3.2 子标签属性解析源码
上边说完了他们的用法,下边我们说说他们是怎么被,spring 从xml配置文件中识别出来的:
meta:
如图所示,就是通过 key - value 获取 meta标签配置的键值对,
依赖 [key, value] 生成了 BeanMetadataAttribute 实例,最后注入了BeanDefinition中
lookup-method:
解析的代码跟meta的解析大同小异。
解析的结束动作,可以视为:就是简单的拿到 lookup-method 标签注入的:抽象方法名称、bean名称然后通过,MethodOverrides 属性间接注入的 BeanDefinition 中
replaced-method:
constructor:
构造函数参数解析,逻辑稍微长了一丢丢,这里主要是因为,构造函数参数可以设置顺序。
如果设置了顺序[index],那么需要校验 数字是否合规,数字是否重复等等问题,最终将解析的结果注入到了 BeanDefinition 中。
property:
跟上边的解析过程大同小异
qualifier:
到此,bean 标签下的,默认标签、元素的解析完成了
6 默认标签中的自定义标签元素解析
下图所示的是:第四章所述的第二段代码,bean 标签下的自定义标签的解析。
下一篇文章将细讲,这里只做简单的介绍。
- 遍历读取标签
浅浅的说一下下图的行为:
1 根据标签识别其所属的命名空间
2 跳过 spring 默认命名空间下的标签
3 根据命名空间获取,该非默认命名空间标签的,处理器 【NamespaceHandler】你或许会好奇,怎么突然蹦出个:NamespaceHandler啊,前文并没有任何地方提到它啊?实际上,NamespaceHandler,由自定义标签的人提供,如果我们自定义了自己的标签那么我们需要在 spring 解析配置前,去容器中注入我们自己开发的:NamespaceHandler
4 解析非默认命名空间标签 【下一篇文章细说,非默认命名空间 - 标签,的解析】
7 BeanDefinition 的注册
将前文解析到的 BeanDefinition 注册到,容器中。
经过前文介绍可知, XmlBeanFactory 继承了一个接口,没错,就是下图所述的接口:
- BeanDefinitionRegistry
这个接口负责对 BeanDefinition 信息的管理。
继续跟踪上图中的
- registerBeanDefinition() 方法,来到此行的终点,
- 已知 BeanDefinitionReaderUtils.registerBeanDefinition() 的参数:BeanDefinitionRegistry registry是个接口,那么上哪去找它的实现类呢?当然是:XmlBeanFactory 的 类图了:这下该知道方法实现在哪了吧?
下边代码中最核心的一句代码:
this.beanDefinitionMap.put(beanName, beanDefinition);
这就是说:BeanDefinitionRegistry 通过 Map 以键值对形式管理beanDefinition 的直接证据。
// 通过 beanName 注册/记录 @Overridepublic void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {// 空校验Assert.hasText(beanName, "Bean name must not be empty");Assert.notNull(beanDefinition, "BeanDefinition must not be null");// 是否是AbstractBeanDefinition 子类 if (beanDefinition instanceof AbstractBeanDefinition) {try {// 注册前最后一次校验,不同于xml校验// 它是对 类定义的(AbstractBeanDefinition) methodOverrides属性的校验// 校验其是否于工厂方法并存、 是否存在(??)((AbstractBeanDefinition) beanDefinition).validate();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,"Validation of bean definition failed", ex);}}BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);// 检查是否已经注册if (existingDefinition != null) {// 已注册if (!isAllowBeanDefinitionOverriding()) {// 不允许覆盖,抛出异常throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,"Cannot register bean definition [" + beanDefinition + "] for bean "" + beanName +"": There is already [" + existingDefinition + "] bound.");}else if (existingDefinition.getRole() < beanDefinition.getRole()) {// bean 的应用(??范围??) 变化// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTUREif (logger.isWarnEnabled()) {logger.warn("Overriding user-defined bean definition for bean "" + beanName +"" with a framework-generated bean definition: replacing [" +existingDefinition + "] with [" + beanDefinition + "]");}}else if (!beanDefinition.equals(existingDefinition)) {// 关键信息变化,不能视作同一个bean ?? if (logger.isInfoEnabled()) {logger.info("Overriding bean definition for bean "" + beanName +"" with a different definition: replacing [" + existingDefinition +"] with [" + beanDefinition + "]");}}else {if (logger.isDebugEnabled()) {logger.debug("Overriding bean definition for bean "" + beanName +"" with an equivalent definition: replacing [" + existingDefinition +"] with [" + beanDefinition + "]");}}// 类定义BeanDefinition 维护到线程安全的 Map 中this.beanDefinitionMap.put(beanName, beanDefinition);}else {// 还未注册过if (hasBeanCreationStarted()) {// Cannot modify startup-time collection elements anymore (for stable iteration)synchronized (this.beanDefinitionMap) {this.beanDefinitionMap.put(beanName, beanDefinition); // 维护map List updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);updatedDefinitions.addAll(this.beanDefinitionNames);updatedDefinitions.add(beanName);this.beanDefinitionNames = updatedDefinitions;if (this.manualSingletonNames.contains(beanName)) {Set updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);updatedSingletons.remove(beanName);this.manualSingletonNames = updatedSingletons;}}}else {// Still in startup registration phasethis.beanDefinitionMap.put(beanName, beanDefinition);this.beanDefinitionNames.add(beanName);this.manualSingletonNames.remove(beanName);}this.frozenBeanDefinitionNames = null;}if (existingDefinition != null || containsSingleton(beanName)) {resetBeanDefinition(beanName);}else if (isConfigurationFrozen()) {clearByTypeCache();}}
8 触发响应事件
再看事件监听器,没错它是从 XmlBeanDefinitionReader 中注入的,你看世界又闭环了。
【PS * 到了这里,你可能已经忘了 XmlBeanDefinitionReader是谁了,不急我来给你重新介绍下:】
你看下图的setter 方法,这里明显是支持注入自定义监听器的,没有自定义则直接注入默认的监听器。
9 结语
9.1 前文总结
到此,本文终于结束了,spring 默认命名空间下的标签已经解析结束了。
至此,BeanDefinitionRegistry 中已经注册好了 BeanDefinition 的信息了;后续,在 getBean() 的流程中, BeanDefinitionRegistry 中注册的 BeanDefinition 将再次粉墨登场。
<如果你不关注:第三方定义的命名空间怎么解析;你可以跳过下一篇文章,直接看getBean 到底干了啥了>
回顾下,本文提到了spring 的4个标签,我们用了绝大部分的篇幅在讲, bean 标签及其子标签、属性的解析,是因为另外的三个标签不重要吗?
- 是的,它们不重要。而且它们的解析过程,要么极其简单,要么就是对 bean 标签解析的套娃[递归] 应用,所以这里讲 bean 标签的解析就已经达到目的了。
- 如果,你看完了bean 标签解析,还看不懂另外三个标签的解析,那么你需要注意,你是否进度拉太快了,之前的内容你消化了么?
————————
beans: 它的实质就是递归调用 bean 标签的解析过程
alias: 为bean注册别名,方便同一个bean可以通过不同的beanName 来引用,代码也简单就不展开了
bean: 老熟人了,不解释
import: 下图就是 import 标签的解析,看看标注的那行代码?是不是一眼顶针? 小黑子在每个地方都会非常的显眼。
- getReaderContext().getReader() 获取的不就是 当前 XmlBeanFactory 上的 XmlBeanDefinitionReader 么?所以,世界又重启了呀,我们又回答了苹果摊前
至于 XmlBeanFactory 不需要介绍了吧?再问紫纱。
————————
9.2 整点正常的活:
如下截图里从左到右的几个类,也是XmlBeanFactory 解析的大致流程。
这里看第三个类的名字? 直译过来,这不是我们一直反复念叨的:
- 默认标签解析么
既然有了默认 标签解析类,那会不会存在一个:自定义标签解析器类呢? 它会不会也跟 DefaultBeanDefinitionDocumentReader 一样,实现了: BeanDefinitionDocumentReader 接口呢?
亦或者自定义标签的解析 也借助: DefaultBeanDefinitionDocumentReader 来完成,但是解析,为了解析自定义标签,我们会不会对: DefaultBeanDefinitionDocumentReader 上,做点别的配置呢?
带着上述两个猜想,我们进入下一章节的旅行,在该章节中,我们将亲自解开上述问题的答案。
关键词:
-
天天热推荐:面试题百日百刷-HBase中HTable API有没有线程安全问题,在程序是单例还是多例?
锁屏面试题百日百刷,每个工作日坚持更新面试题。请看到最后就能获取你想要的,接下来的是今日的面试题:...
来源: 环球观热点:《系列一》-- 4、xml配置文件解析之[默认]命名空间[标签]的解析
天天热推荐:面试题百日百刷-HBase中HTable API有没有线程安全问题,在程序是单例还是多例?
IPX6级防水防刮:宏碁墨尔本背包169元抄底(三种款式)
焦点快播:博主发薅高铁商务座羊毛攻略 20元享超VIP服务网友效仿:12306回应怒赞
环球快消息!平台回应机票一分钟三次变价:实时价格变动正常
英雄之光|陈旧的记录本 是他牵挂群众最温暖的见证
世界即时看!你的工资不能低于这数!31省份最低工资公布:时薪达标没
世界最资讯丨山东推出399元高铁环游套票:有效期5天、全省免费换乘
每日热议!DIY万能钥匙!主板检测灯你不得不懂
【焦点热闻】09款奥迪A4L标准型改装泪眼/导航作业
最新资讯:Docker-compose 到 Kubernetes 的迁移工具!
世界速看:全新深红配色亮相!iPhone 15 Pro超高清外观渲染图首曝:钛金属边框、Type-C接口
世界资讯:诈骗网红梅尼耶的MCN游良文化被申请破产:小刚学长等多位网红受骗
焦点速读:Java性能权威指南(第2版)读后总结与感想
动态:大学招聘体育老师 要求得过奥运冠军引热议:官方回应专业技能很重要
复星旅文2022年收入137.78亿元 徐晓亮:要尽快追回过去三年失去的业绩
【天天报资讯】K8S圣经12:SpringCloud+Jenkins+ K8s Ingress 自动化灰度发布
回顾、信号、flask-script、sqlalchemy介绍和快速使用、创建操作数据表
今日快看!ASP.NET Core MVC 从入门到精通之初窥门径
女主不够性感吗?《生化危机4重制版》发售两周狂卖超400万份:Steam好评如潮
Intel中国特供i5-13490F/i7-13790F闪电降价:性价比更神了!
天天看热讯:男人多次失恋后和娃娃订婚 还“生”了三个孩子
当年找抖音赔30亿的腾讯视频 这会儿怎么来世纪大和解了?
电视接口盘点 HDMI 2.1真的是刚需吗?
天天观点:罪恶都市任务攻略_侠盗飞车罪恶都市任务做完了怎么办
环球短讯!HRB500钢筋符号_HRB500的钢筋符号是什么 属于几级钢筋
热头条丨【调试】ftrace(三)trace-cmd和kernelshark
全球观天下!集成Unity3D到iOS应用程序中
环球视点!OpenCV获取相机旋转矩阵和平移矩阵
海信电视精简系统
【全球聚看点】试验设计课程作业
比亚迪海豹、长安深蓝SL03获央视第三届《中国汽车风云盛典》评委会大奖
诈骗网红梅尼耶的MCN被申请破产引热议 多位女网红等都受害:网友吐槽行业乱
世界即时看!女子开宝马占用商场特斯拉专用车位 被特斯拉怒堵2天
世界速递!2023.4.7【模板】快速沃尔什变换FWT
今日报丨面试题百日百刷-HBase HRegionServer宕机如何处理
第135篇:Three.js基础入门
每日消息!交易商协会评估更新定向债务融资工具专项机构投资人名单
美国3月非农就业人口增幅降至23.6万 失业率为3.5%
热文:构造柱的作用是什么_构造柱的作用
焦点热讯:网友称余额宝页面显示乱码 支付宝回应:正在修复 不影响资金安全
《龙马精神》电影中真打实摔 成龙:我69岁动作比你还快
热点!说十个需要送老婆礼物的节日
焦点观察:火热出炉 秘汁全鸡的数字新“味”
大阳睿能全新动力首款车型H12下线:电机1700W 续航150公里
249元 小米米家自动真空封口机发布:-70KPa大吸力
全球快资讯丨世界各地小孩的玩具对比:不止文化与财富的差距
当前动态:马斯克开源推特算法反被指责:隐藏重要细节、与承诺不符
【当前独家】《王者荣耀》S31赛季4月13日上线 新英雄姬小满来了
深圳开放大学优秀学生李德炎:保持学习状态,争做行业模范
天天快看点丨自动旋转ROS小车(rviz+urdf+xacro)(附加python操作键盘控制小车运动)
每日资讯:java -- Math、BigInteger、BigDecimal类和基本类型的包装类、正则表达式
【快播报】黑田东彦“卸任”言论释放宽松信号 日债收益率曲线平坦化下移
速递!定价全球最低!国产科幻FPS《边境》国区售价68元起
天天观热点:孟羽童已不是董明珠秘书引热议 本人回应:很享受格力市场营销工作
今日看点:米粉换上Redmi Note 12 Turbo:陪伴他5年的小米6正式退役
天天即时看!网友看电影觉得难看成功退一半费用 影城:散场20分钟内可办理
电动自行车调速器网上公开售卖!专家:私改限速或引发燃爆事故
环球资讯:ps 备忘清单_开发速查表分享
天天观天下!王者更新:祈愿夺宝重启,520传说天幕返场,5英雄喜提新衣
焦点速读:离谱!观致汽车要倒台 车主也被拉下水:被厂商告了
全球气象预报大模型风乌发布:有效预报时间首破10天
事关“刹车失灵”争议核心数据 本田中国召回超20万辆雅阁
长城财报漂亮 是因为新能源汽车卖得不漂亮
全球新资讯:仅1999元!铁威马F4-423(4G)四盘位NAS开启预售:双2.5G网口
全球速读:大美游轮2022年亏损2511.24万同比亏损增加 游轮运营业务毛利减少
Privilege Escalation 权限提升
即时焦点: 如何处理Xcode上传IPA文件后无法在后台架构版本中显示的问题?
当前要闻:易基因:群体分析揭示了DNA甲基化在番茄驯化和代谢多样性中的作用|组学研究
记录-VueJs中如何使用Teleport组件
Springfox与SpringDoc——swagger如何选择(SpringDoc入门)
澳大利亚一飞机掉入印度洋:全员坠海 未有伤亡
世界速递!比亚迪大疆达成合作!全新海狮将用上高级辅助驾驶技术:纯视觉走天下
每日消息!希捷推出星球大战版SSD:三款RGB光剑任选
资讯推荐:一图看懂!小米/红米多款热门机型官方降价:小米12S/13全系有活动
环球新动态:用两年就卡?3分钟学会选电视硬件
当前播报:申城交警多措并举加强高速公路和城市快速路事故预防工作
世界头条:用 Go 剑指 Offer 17. 打印从1到最大的n位数
【天天时快讯】获取Python函数信息的方法
世界信息:GPT对SaaS领域有什么影响?
全球新资讯:什么是 Java 字节码?采用字节码的好处是什么?
【天天聚看点】ubuntu离线安装tcpdump
因债券承销尽调不充分等问题 民生证券被上交所出具书面警示
每日视讯:最新确认:小米13 Ultra用上了USB 3.X接口
《流浪地球2》4月14日网络首播!导演郭帆:修改了一百多个视效镜头
差评高达86%!艺画开天官博恢复《三体》动画相关微博
【世界聚看点】等等党狂喜!比亚迪海豹有优惠了:本月订车至享高3.1万元减免
全球热门:荣耀Magic5 Pro“首碎”!SUV压过屏幕依旧完好
每日热闻!微信界面黑色怎么设置成白色_微信变成黑色怎么调过来
【独家】使用Drone+gitea配置自己的CICD流程
全球热消息:收评:两市震荡走强创指涨0.84% 医药、人工智能概念涨幅居前
最资讯丨马来西亚原装进口:猫山王榴莲雪糕4元/支狂促
索尼痛斥英国CMA:偏袒微软过于荒谬
当前头条:合资A级轿车更难了!2023款比亚迪秦PLUS EV冠军版上市:12.98万起
苹果中国杀疯!iPhone14售价跌破5000元 买它还是华为P60?
环球要闻:网红密子君带货无骨鸡爪!粉丝提醒她有蟑螂 本人道歉
保罗:比赛起起伏伏很奇怪 从未跟KD这种能吸引包夹的球员共事过
焦点热门:全文索引:Apache Lucene(一)
天天热讯:Java 自增自减运算符和移位运算符介绍
世界观速讯丨NTP时间同步服务器(频率同步)包含帧同步、载波同步、位同步