Spring IOC:invokeBeanFactoryPostProcessors调用链
参考资料
《Spring IoC源码学习:invokeBeanFactoryPostProcessors 详解》
前文:
《Spring IOC:obtainFreshBeanFactory调用链》
写在开头:本文为个人学习笔记,内容比较随意,夹杂个人理解,如有错误,欢迎指正。
目录
一、概述
二、invokeBeanFactoryPostProcessors
1、getBeanFactoryPostProcessors
2、invokeBeanFactoryPostProcessors
三、getBeanFactoryPostProcessors
1、getBeanFactoryPostProcessors
2、添加自定义BeanFactoryPostProcessor
三、invokeBeanFactoryPostProcessors
1、区分BeanDefinitionRegistryPostProcessor与BeanFactoryPostProcessor
2、根据优先级实现BeanDefinitionRegistryPostProcessor
3、实例化剩余BeanDefinitionRegistryPostProcessors与部分BeanFactoryPostProcessor
4、针对BeanFactoryPostProcessor重复2、3步操作
总结:
一、概述
invokeBeanFactoryPostProcessors方法会实例化和调用所有 BeanFactoryPostProcessor(包括其子类 BeanDefinitionRegistryPostProcessor)。
BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 时对外暴露的扩展点,Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例化任何 bean 之前读取 bean 的定义,并可以修改它。
二、invokeBeanFactoryPostProcessors
2个重要步骤:
1、getBeanFactoryPostProcessors
拿到当前应用上下文beanFactoryPostProcessors变量中的值
2、invokeBeanFactoryPostProcessors
实例化并调用所有已注册的BeanFactoryPostProcessor
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {// getBeanFactoryPostProcessors(): 拿到当前应用上下文beanFactoryPostProcessors变量中的值// invokeBeanFactoryPostProcessors: 实例化并调用所有已注册的BeanFactoryPostProcessorPostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}
}
三、getBeanFactoryPostProcessors
1、getBeanFactoryPostProcessors
拿到当前应用上下文中已经注册的 BeanFactoryPostProcessor,默认情况下返回为空。
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {return this.beanFactoryPostProcessors;
}
2、添加自定义BeanFactoryPostProcessor
在《Spring IOC:从ContextLoaderListener到AbstractApplicationContext》中介绍的customizeContext方法会通过determineContextInitializerClasses方法读取web.xml中的参数(globalInitializerClasses与contextInitializerClasses),初始化实现了ApplicationContextInitializer接口的类。
protected void customizeContext(ServletContext sc, ConfigurableWebApplicationContext wac) {//获取初始化器类集合List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> initializerClasses =determineContextInitializerClasses(sc);for (Class<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerClass : initializerClasses) {Class<?> initializerContextClass =GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class);if (initializerContextClass != null && !initializerContextClass.isInstance(wac)) {throw new ApplicationContextException(String.format("Could not apply context initializer [%s] since its generic parameter [%s] " +"is not assignable from the type of application context used by this " +"context loader: [%s]", initializerClass.getName(), initializerContextClass.getName(),wac.getClass().getName()));}//实例化初始化器并添加到集合中this.contextInitializers.add(BeanUtils.instantiateClass(initializerClass));}//排序并执行,编号越小越早执行AnnotationAwareOrderComparator.sort(this.contextInitializers);for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : this.contextInitializers) {initializer.initialize(wac);}}protected List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>>determineContextInitializerClasses(ServletContext servletContext) {List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> classes =new ArrayList<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>>();//通过<context-param>属性配置globalInitializerClasses获取全局初始化类名String globalClassNames = servletContext.getInitParameter(GLOBAL_INITIALIZER_CLASSES_PARAM);if (globalClassNames != null) {for (String className : StringUtils.tokenizeToStringArray(globalClassNames, INIT_PARAM_DELIMITERS)) {classes.add(loadInitializerClass(className));}}//通过<context-param>属性配置contextInitializerClasses获取容器初始化类名String localClassNames = servletContext.getInitParameter(CONTEXT_INITIALIZER_CLASSES_PARAM);if (localClassNames != null) {for (String className : StringUtils.tokenizeToStringArray(localClassNames, INIT_PARAM_DELIMITERS)) {classes.add(loadInitializerClass(className));}}return classes;}@SuppressWarnings("unchecked")private Class<ApplicationContextInitializer<ConfigurableApplicationContext>> loadInitializerClass(String className) {try {// 实例化classNameClass<?> clazz = ClassUtils.forName(className, ClassUtils.getDefaultClassLoader());if (!ApplicationContextInitializer.class.isAssignableFrom(clazz)) {// 校验clazz是否实现了ApplicationContextInitializer接口, 如果没有则抛异常throw new ApplicationContextException("Initializer class does not implement ApplicationContextInitializer interface: " + clazz);}// clazz强转成ApplicationContextInitializer, 并返回return (Class<ApplicationContextInitializer<ConfigurableApplicationContext>>) clazz;} catch (ClassNotFoundException ex) {throw new ApplicationContextException("Failed to load context initializer class [" + className + "]", ex);}
}
我们通过新建一个ApplicationContextInitializer的实现类并重写initialize方法实现个性化逻辑,在其中手动添加继承了BeanFactoryPostProcessor接口的MyBeanFactoryPostProcessor。并通过globalInitializerClasses将其注册到上下文中,就可以实现beanFactoryPostProcessors的预存功能。
public class MyApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>
{public void initialize(ConfigurableApplicationContext applicationContext) {MyBeanFactoryPostProcessor myBeanFactoryPostProcessor = new MyBeanFactoryPostProcessor();applicationContext.addBeanFactoryPostProcessor(myBeanFactoryPostProcessor);System.out.println("将自定义的MyBeanFactoryPostProcessor添加到应用上下文中");}
}
<context-param><param-name>globalInitializerClasses</param-name><param-value>com.test.MyApplicationContextInitializer</param-value>
</context-param>
三、invokeBeanFactoryPostProcessors
首先要介绍下BeanFactoryPostProcessor及其子类BeanDefinitionRegistryPostProcessor。
BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 时对外暴露的扩展点,Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例化任何 bean 之前读取 bean 的定义,并可以修改它。
BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor,比 BeanFactoryPostProcessor 具有更高的优先级,主要用来在常规的BeanFactoryPostProcessor 检测开始之前执行。特别是,你可以通过BeanDefinitionRegistryPostProcessor来注册一些常规的BeanFactoryPostProcessor。因为此时所有常规的 BeanFactoryPostProcessor都还没开始被处理。
对于BeanFactoryPostProcessor的介绍可以看我之前写的文章《传送门》
由于invokeBeanFactoryPostProcessors整段代码较长,这里按照执行步骤拆分成了几段,如下图所示。
public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {1、区分BeanDefinitionRegistryPostProcessor与BeanFactoryPostProcessor2、根据优先级实现BeanDefinitionRegistryPostProcessor3、实例化剩余BeanDefinitionRegistryPostProcessors与部分BeanFactoryPostProcessor4、针对BeanFactoryPostProcessor重复2、3步操作
}
1、区分BeanDefinitionRegistryPostProcessor与BeanFactoryPostProcessor
遍历入参beanFactoryPostProcessors,并区分开BeanDefinitionRegistryPostProcessor与BeanFactoryPostProcessor,前者比后者多一步直接执行其postProcessBeanDefinitionRegistry方法,然后分别存入registryProcessors 与regularPostProcessors中。
注意:这里存储和实现的是作为参数传的beanFactoryPostProcessors,即我们在前文中介绍的利用ApplicationContextInitializer拓展实现的BeanFactoryPostProcessor,不包括在容器中注册的BeanFactoryPostProcessor。
Set<String> processedBeans = new HashSet<String>();// 判断beanFactory是否为BeanDefinitionRegistry,beanFactory为DefaultListableBeanFactory,// 而DefaultListableBeanFactory实现了BeanDefinitionRegistry接口,因此这边为trueif (beanFactory instanceof BeanDefinitionRegistry) {BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;// 用于存放普通的BeanFactoryPostProcessorList<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();// 用于存放BeanDefinitionRegistryPostProcessorList<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();// 首先处理入参中的beanFactoryPostProcessors// 遍历所有的beanFactoryPostProcessors, 将BeanDefinitionRegistryPostProcessor和普通BeanFactoryPostProcessor区分开for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {// 如果是BeanDefinitionRegistryPostProcessorBeanDefinitionRegistryPostProcessor registryProcessor =(BeanDefinitionRegistryPostProcessor) postProcessor;// 直接执行BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法registryProcessor.postProcessBeanDefinitionRegistry(registry);// 添加到registryProcessors(用于最后执行postProcessBeanFactory方法)registryProcessors.add(registryProcessor);} else {// 否则,只是普通的BeanFactoryPostProcessor// 添加到regularPostProcessors(用于最后执行postProcessBeanFactory方法)regularPostProcessors.add(postProcessor);}}
2、根据优先级实现BeanDefinitionRegistryPostProcessor
(1)找出所有实现BeanDefinitionRegistryPostProcessor接口的Bean的beanName,存入postProcessorNames中(这里beanName是通过beanFactory.getBeanNamesForType从前一步obtainFreshBeanFactory方法中注册的beanName中找出的)
(2)遍历postProcessorNames,过滤出实现了PriorityOrdered接口(排序用)的beanName。
(3)使用beanFactory.getBean方法创建该BeanDefinitionRegistryPostProcessor对应的bean对象。将创建完成的bean对象存入currentRegistryProcessors,并将该beanName存入processedBeans。
(4)根据PriorityOrdered接口的实现情况对currentRegistryProcessors排序,然后将currentRegistryProcessors存入registryProcessors中。
(5)遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法。执行完毕后, 清空currentRegistryProcessors。
(6)重复1-5步的过程,但会重新获取postProcessorNames,这是因为执行完上面的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,可能会新增了其他的BeanDefinitionRegistryPostProcessor, 因此需要重新查找。且这一步针对的是Ordered接口而不是PriorityOrdered接口。
// 用于保存本次要执行的BeanDefinitionRegistryPostProcessorList<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();// 调用所有实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor实现类// 找出所有实现BeanDefinitionRegistryPostProcessor接口的Bean的beanNameString[] postProcessorNames =beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);// 遍历postProcessorNamesfor (String ppName : postProcessorNames) {// 校验是否实现了PriorityOrdered接口if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {// 获取ppName对应的bean实例, 添加到currentRegistryProcessors中,// beanFactory.getBean: 这边getBean方法会触发创建ppName对应的bean对象, 目前暂不深入解析currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));// 将要被执行的加入processedBeans,避免后续重复执行processedBeans.add(ppName);}}// 进行排序(根据是否实现PriorityOrdered、Ordered接口和order值来排序)sortPostProcessors(currentRegistryProcessors, beanFactory);// 添加到registryProcessors(用于最后执行postProcessBeanFactory方法)registryProcessors.addAll(currentRegistryProcessors);// 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);// 执行完毕后, 清空currentRegistryProcessorscurrentRegistryProcessors.clear();// 调用所有实现了Ordered接口的BeanDefinitionRegistryPostProcessor实现类(过程跟上面的步骤3基本一样)// 找出所有实现BeanDefinitionRegistryPostProcessor接口的类, 这边重复查找是因为执行完上面的BeanDefinitionRegistryPostProcessor,// 可能会新增了其他的BeanDefinitionRegistryPostProcessor, 因此需要重新查找postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {// 校验是否实现了Ordered接口,并且还未执行过if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);}}sortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);// 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);currentRegistryProcessors.clear();
3、实例化剩余BeanDefinitionRegistryPostProcessors与部分BeanFactoryPostProcessor
(1)调用beanFactory.getBeanNamesForType找出所有实现BeanDefinitionRegistryPostProcessor接口的类,并跳过已经执行过的。
(2)重复上一节中3、4、5步操作。
(3)从registryProcessors中取出所有的BeanDefinitionRegistryPostProcessor,执行其postProcessBeanFactory方法。
(4)调用入参beanFactoryPostProcessors中BeanFactoryPostProcessor的postProcessBeanFactory方法。
// 最后, 调用所有剩下的BeanDefinitionRegistryPostProcessorsboolean reiterate = true;while (reiterate) {reiterate = false;// 找出所有实现BeanDefinitionRegistryPostProcessor接口的类postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {// 跳过已经执行过的if (!processedBeans.contains(ppName)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);// 如果有BeanDefinitionRegistryPostProcessor被执行, 则有可能会产生新的BeanDefinitionRegistryPostProcessor,// 因此这边将reiterate赋值为true, 代表需要再循环查找一次reiterate = true;}}sortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);// 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);currentRegistryProcessors.clear();}// 6.调用所有BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法(BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor)invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);// 最后, 调用入参beanFactoryPostProcessors中的普通BeanFactoryPostProcessor的postProcessBeanFactory方法invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);} else {invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);}
4、针对BeanFactoryPostProcessor重复2、3步操作
前三步之后,所有的BeanDefinitionRegistryPostProcessor都已处理完毕,包括入参beanFactoryPostProcessors和容器中注册的已经全部处理完毕,下面开始处理容器中的所有BeanFactoryPostProcessor。
第4步则模仿前2步的操作,不过将BeanDefinitionRegistryPostProcessor替换为了BeanFactoryPostProcessor。
// 找出所有实现BeanFactoryPostProcessor接口的类String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);// 用于存放实现了PriorityOrdered接口的BeanFactoryPostProcessorList<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();// 用于存放实现了Ordered接口的BeanFactoryPostProcessor的beanNameList<String> orderedPostProcessorNames = new ArrayList<String>();// 用于存放普通BeanFactoryPostProcessor的beanNameList<String> nonOrderedPostProcessorNames = new ArrayList<String>();// 遍历postProcessorNames, 将BeanFactoryPostProcessor按实现PriorityOrdered、实现Ordered接口、普通三种区分开for (String ppName : postProcessorNames) {// 跳过已经执行过的if (processedBeans.contains(ppName)) {} else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {// 添加实现了PriorityOrdered接口的BeanFactoryPostProcessorpriorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));} else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {// 添加实现了Ordered接口的BeanFactoryPostProcessor的beanNameorderedPostProcessorNames.add(ppName);} else {// 添加剩下的普通BeanFactoryPostProcessor的beanNamenonOrderedPostProcessorNames.add(ppName);}}// 调用所有实现PriorityOrdered接口的BeanFactoryPostProcessor// 对priorityOrderedPostProcessors排序sortPostProcessors(priorityOrderedPostProcessors, beanFactory);// 遍历priorityOrderedPostProcessors, 执行postProcessBeanFactory方法invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);// 调用所有实现Ordered接口的BeanFactoryPostProcessorList<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();for (String postProcessorName : orderedPostProcessorNames) {// 获取postProcessorName对应的bean实例, 添加到orderedPostProcessors, 准备执行orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}// 对orderedPostProcessors排序sortPostProcessors(orderedPostProcessors, beanFactory);// 遍历orderedPostProcessors, 执行postProcessBeanFactory方法invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);// 调用所有剩下的BeanFactoryPostProcessorList<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();for (String postProcessorName : nonOrderedPostProcessorNames) {// 获取postProcessorName对应的bean实例, 添加到nonOrderedPostProcessors, 准备执行nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}// 遍历nonOrderedPostProcessors, 执行postProcessBeanFactory方法invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);// 清除元数据缓存(mergedBeanDefinitions、allBeanNamesByType、singletonBeanNamesByType),// 因为后处理器可能已经修改了原始元数据,例如, 替换值中的占位符...beanFactory.clearMetadataCache();
总结:
整个流程先从上下文中获取globalInitializerClasses、contextInitializerClasses参数配置的扩展点中手动添加到上下文中的BeanFactoryPostProcessor与BeanDefinitionRegistryPostProcessor。
然后将他们分开存储,并实现BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法。再获取beanFactory中注册的BeanDefinitionRegistryPostProcessor,过滤出实现了PriorityOrdered接口的beanName,排序后依次实现。同样的步骤再针对Ordered接口重复执行。最后将beanFactory中剩余的BeanDefinitionRegistryPostProcessor类型的beanName依次执行postProcessBeanDefinitionRegistry方法。最后,调用入参beanFactoryPostProcessors中的BeanFactoryPostProcessor的postProcessBeanFactory方法。
再然后,重复BeanDefinitionRegistryPostProcessor的处理过程,将对象替换为BeanFactoryPostProcessor。
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- 不懂得小程序运营,试试会员运营体系
如今互联网营销时代,有很多有商家搭建了自己的微信小程序,但大多数商家不懂得小程序运营,该用什么方式去实现小程序的引流获客。 想要做好小程序的引流营销作用,就必须做好小程序运营,加强小程序的曝光,让…...
2024/4/7 17:52:40 - Jtag调试技巧
Jtag调试技巧 Jtag一般调试方式,是在整个工程运行时,必须擦除bootload段,才能进行相应的jtag调试。下面介绍一下,程序运行时直接进行jtag调试方法: 1.首先连接jtag服务。 2.ckcore-elf-gdb -nx 3.add-symbol-file mai…...
2024/4/18 19:13:23 - 关于 ERROR 1049 (42000): Unknown database ‘root‘ 的一种原因
在使用参数登录 MySQL 的时候,可能会遇到,使用的用户名和密码都对,但提示错误, ERROR 1049 (42000): Unknown database ‘root’ 的情况, 这种情况,其中的一种原因,是你指定的参数不对ÿ…...
2024/4/7 17:52:36 - 使用InDesign 2022创建具有吸引力的边注栏的细节
欢迎观看indesign教程,小编带大家学习 InDesign 2022的基本工具和使用技巧,了解如何使用简单的文本框工具灵活创建边注栏,添加重要信息。 如果想要在这个文件中添加一个边注栏,来到工具面板选择「文字工具」,然后点击…...
2024/4/7 17:52:35 - 肯德基在线点餐CPS接口-肯德基在线点餐5折优惠接口 KFC点餐折扣API 聚推客联盟开放平台
基本信息 该接口用于聚推客联盟平台所有活动获取推广链接接口,全部活动的推广链接从这一个接口获取。肯德基在线点餐活动ID为16,设置act_id为16,就可以只获得肯德基在线点餐的活动推广链接了。 在线测试 接口地址:http://api.j…...
2024/4/14 2:01:28 - android studio 无法调试手机 一直在 wait for debug
以前只是在自己魅族手机上出现,以为是魅族手机问题,后来在其它手机上也陆续出现,原来的解决方法不管用了。 现在发现了新方法 当手机停留在wait for debug 界面时,在 android studio 中找到这个按钮,附加 选择你要调…...
2024/4/7 17:52:34 - arcgis for js实现风场
一、风场工具类封装 二、风场调用 三、风场展示效果 如果对您有帮助 感谢支持技术分享,请扫码点赞支持: 技术合作交流qq:2401315930...
2024/4/14 2:01:33 - java实现线程的等待与唤醒
写好true和false变化的方法 private static volatile boolean flag true;public static void stopTask() {flag false;}public static void startTask() {flag true;} 多次调用单个线程(定时任务模拟调用线程) Scheduled(cron "*/1 * * * * ?&…...
2024/4/14 2:01:13 - Assignment写作需要遵循哪些原则?
留学Assignment写作在大体上是一致的,不论是科研assignment,还是学术性的assignment,虽然不同的老师可能会有不同的要求,但总体上来说是没有多大差异的。一般来说assignment写作所遵循的原则是相同的,对于不同的写作要…...
2024/4/19 14:16:23 - PYTORCH 笔记 DILATE 代码解读
dilate 完整代码路径:vincent-leguen/DILATE: Code for our NeurIPS 2019 paper "Shape and Time Distortion Loss for Training Deep Time Series Forecasting Models" (github.com) 1 main 函数 1.1 导入库 import numpy as np import torch from da…...
2024/4/14 2:01:23 - 中国旋装玻璃市场现状研究分析与发展前景预测报告
2022-2028中国旋装玻璃市场现状研究分析与发展前景预测报告 【报告篇幅】:85 【报告图表数】:127 【报告出版时间】:2022年1月 【报告出版机构】:恒州博智(QYR)化工及材料研究中心 详细内容请参考完整版报告 据QYR最新调研&…...
2024/4/14 2:01:28 - 897. 最长公共子序列
897. 最长公共子序列 给定两个长度分别为 N 和 M 的字符串 A 和 B,求既是 A 的子序列又是 B 的子序列的字符串长度最长是多少。 输入格式 第一行包含两个整数 N 和 M。 第二行包含一个长度为 N 的字符串,表示字符串 A。 第三行包含一个长度为 M 的字…...
2024/4/16 21:29:28 - 重载和重写以及多态的简述
重载 1.注意事项: (1)方法的重载必须在同一类中 (2)方法的名字必须一样 (3)方法的参数必须不一样 (4)返回值可以一样也可以不一样 (5)同一类…...
2024/4/14 2:01:28 - C++开发短信验证码通知短信
提供可靠的用户手机认证服务 异常拦截、失败补呼、语音补呼等综合手段,为您提供高可靠的用户手机验证服务。 1 C对接验证码短信接口DEMO示例 本文为您提供了C版本的验证码短信接口对接DEMO示例 * 接口类型:触发短信接口,支持发送验证码短信、…...
2024/4/14 2:01:38 - 骨传导耳机有哪些牌子好?好用的骨传导耳机推荐
在生活中,耳机对于我们来说是必需品,目前市面上的耳机从有线耳机到蓝牙无线耳机,再到挂脖式蓝牙耳机种类多样化。其形态和技术也有了更多的创新。不管耳机怎么变化,都不适合长时间佩戴,入耳式耳机长时间佩戴耳朵就会产…...
2024/4/14 2:01:38 - 短信链接复制搜索公众号,短信如何推广公众号?
复制搜索公众号H5在线免费制作,短信链接推广公众号必备神器;复制自动提示搜索公众号,引导关注关注。 我们使用短信推广公众号关注的过程中可能希望对方搜索关注公众号;如果直接让用户搜索关注的话操作比较麻烦,我们可…...
2024/4/17 22:32:58 - Android 高级UI,android开发艺术探索
标签可以删减多余的层级,它多用于替换FrameLayout或者当一个布局包含另一个时,消除视图层次结构中多余的视图组 [html] view plain copy <merge xmlns:android“http://schemas.android.com/apk/res/android”> <Button android:layout_width“fill_pa…...
2024/4/16 18:43:53 - 如何成为一名程序员
最近有一部剧爆火了,这部剧就是《开端》。而由白敬亭主演的肖鹤云也是给我们大家留下了深刻的印象,不仅遇事机智果断,而且冷静。看过这部剧的伙伴都知道,肖鹤云是一个做游戏的,就是我们口中常说的程序员,他…...
2024/4/16 22:50:22 - 应用策略模式重构并扩展祖传if...else...
重构前: public String saveMessage(SmsSendFormPo smsSendFormPo) {List<String> userIdList DrinStringUtils.str2List(smsSendFormPo.getUserIds(), ",");String otherReceiverPhone smsSendFormPo.getOtherReceiverPhone();List<String&g…...
2024/4/14 2:01:18 - 字符串计算
3. 无重复字符的最长子串 var lengthOfLongestSubstring function(s) {let max 0;for(let i 0; i < s.length; i) {let len 1, flag false;for(let j i1; j < s.length; j) {len j - i;let str s.substr(i, len);if (str.indexOf(s[j]) ! -1) {flag false;break…...
2024/4/7 17:52:23
最新文章
- 第一篇【传奇开心果系列】Python深度学习库技术点案例示例:深度解读深度学习在自动驾驶领域的应用
传奇开心果博文系列 系列博文目录Python深度学习库技术点案例示例系列 博文目录前言一、深度学习在自动驾驶方面的应用介绍二、目标检测和识别示例代码三、路况感知示例代码四、行为预测示例代码五、路径规划示例代码六、自动驾驶控制示例代码七、感知融合示例代码八、高精度地…...
2024/4/25 8:08:22 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/3/20 10:50:27 - 前端开发攻略---Vue通过自定义指令实现元素平滑上升的动画效果(可以自定义动画时间、动画效果、动画速度等等)。
1、演示 2、介绍 这个指令不是原生自带的,需要手动去书写,但是这辈子只需要编写这一次就好了,后边可以反复利用。 3、关键API IntersectionObserver IntersectionObserver 是一个用于监测元素是否进入或离开视口(viewport&#x…...
2024/4/24 11:39:38 - 蓝桥杯第十五届抱佛脚(十)贪心算法
蓝桥杯第十五届抱佛脚(十)贪心算法 贪心算法基本概念 贪心算法是一种在算法设计中常用的方法,它在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是最好或最优的算法。 贪…...
2024/4/19 0:49:59 - 备战蓝桥杯Day37 - 真题 - 特殊日期
一、题目描述 思路: 1、统计2000年到2000000年的日期,肯定是需要遍历 2、闰年的2月是29天,非闰年的2月是28天。我们需要判断这一年是否是闰年。 1、3、5、7、8、10、12月是31天,4、6、9、11月是30天。 3、年份yy是月份mm的倍数…...
2024/4/24 9:33:16 - 【外汇早评】美通胀数据走低,美元调整
原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...
2024/4/23 20:58:27 - 【原油贵金属周评】原油多头拥挤,价格调整
原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...
2024/4/23 13:30:22 - 【外汇周评】靓丽非农不及疲软通胀影响
原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...
2024/4/23 13:28:06 - 【原油贵金属早评】库存继续增加,油价收跌
原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...
2024/4/24 18:16:28 - 【外汇早评】日本央行会议纪要不改日元强势
原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...
2024/4/23 13:27:44 - 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响
原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...
2024/4/19 11:57:53 - 【外汇早评】美欲与伊朗重谈协议
原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...
2024/4/23 13:29:53 - 【原油贵金属早评】波动率飙升,市场情绪动荡
原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...
2024/4/23 13:27:22 - 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试
原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...
2024/4/23 13:28:42 - 【原油贵金属早评】市场情绪继续恶化,黄金上破
原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...
2024/4/23 22:01:21 - 【外汇早评】美伊僵持,风险情绪继续升温
原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...
2024/4/23 13:29:23 - 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势
原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...
2024/4/25 0:00:17 - 氧生福地 玩美北湖(上)——为时光守候两千年
原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...
2024/4/25 4:19:21 - 氧生福地 玩美北湖(中)——永春梯田里的美与鲜
原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...
2024/4/19 11:59:23 - 氧生福地 玩美北湖(下)——奔跑吧骚年!
原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...
2024/4/19 11:59:44 - 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!
原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...
2024/4/25 2:10:52 - 「发现」铁皮石斛仙草之神奇功效用于医用面膜
原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...
2024/4/24 16:38:05 - 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者
原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...
2024/4/23 13:28:14 - 广州械字号面膜生产厂家OEM/ODM4项须知!
原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...
2024/4/23 13:27:51 - 械字号医用眼膜缓解用眼过度到底有无作用?
原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...
2024/4/23 13:27:19 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57