SpringBoot源码解读与原理分析(二十)IOC容器的刷新(一)

文章目录

  • 7 IOC容器的刷新
    • 7.1 初始化前的预处理
      • 7.1.1 初始化属性配置
      • 7.1.2 初始化早期事件的集合
    • 7.2 初始化BeanFactory
      • 7.2.1 注解驱动的refreshBeanFactory
      • 7.2.2 XML驱动的refreshBeanFactory
      • 7.2.3 获取BeanFactory
    • 7.3 BeanFactory的预处理配置
      • 7.3.1 ApplicationContextAwareProcessor
        • 7.3.1.1 ApplicationContextAwareProcessor的作用
        • 7.3.1.2 ignoreDependencyInterface
      • 7.3.2 自动注入的支持
      • 7.3.3 ApplicationListenerDetector

7 IOC容器的刷新

上一章完整介绍了SpringBoot应用的启动过程,其中有一个关键步骤,其内部设计相当复杂,即IOC容器的刷新

代码清单1SpringApplication.javapublic ConfigurableApplicationContext run(String... args) {//...//6.3.3 初始化IOC容器prepareContext(context, environment, listeners, applicationArguments, printedBanner);//6.3.4 刷新IOC容器refreshContext(context);//...
}

通过查看源码,refreshContext方法最终会调用AbstractApplicationContext中的refresh方法。

在 SpringBoot源码解读与原理分析(十三)IOC容器的启动流程 中已经从大体上梳理了IOC容器刷新一共做了13件事情,这一章详细梳理这13件事情具体是怎么做的。注意,这一章会分多篇文章来梳理,这篇文章先梳理前面三个步骤(7.1-7.3)。

代码清单2AbstractApplicationContext.javapublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.// 7.1 初始化前的预处理prepareRefresh();// Tell the subclass to refresh the internal bean factory.// 7.2 获取BeanFactory,加载所有bean的定义信息(未实例化)ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.// 7.3 BeanFactory的预处理配置prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.// 7.4 准备BeanFactory完成后进行的后置处理postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.// 7.5 执行BeanFactory创建后的后置处理器invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.// 7.6 注册Bean的后置处理器registerBeanPostProcessors(beanFactory);// Initialize message source for this context.// 7.7 初始化MessageSourceinitMessageSource();// Initialize event multicaster for this context.// 7.8 初始化事件广播器initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.// 7.9 子类的多态onRefreshonRefresh();// Check for listener beans and register them.// 7.10 注册监听器registerListeners();// 至此,BeanFactory创建完成// Instantiate all remaining (non-lazy-init) singletons.// 7.11 初始化所有剩下的单实例finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.// 7.12 完成容器的创建工作finishRefresh();} catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;} finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...// 7.13 清理缓存resetCommonCaches();}}
}

7.1 初始化前的预处理

// 7.1 初始化前的预处理
prepareRefresh();
代码清单3AbstractApplicationContext.javaprotected void prepareRefresh() {// Switch to active.// 记录刷新动作执行的事件this.startupDate = System.currentTimeMillis();// 标记当前IOC容器已激活this.closed.set(false);this.active.set(true);if (logger.isDebugEnabled()) {if (logger.isTraceEnabled()) {logger.trace("Refreshing " + this);} else {logger.debug("Refreshing " + getDisplayName());}}// Initialize any placeholder property sources in the context environment.// 7.1.1 初始化属性配置initPropertySources();// Validate that all properties marked as required are resolvable:// see ConfigurablePropertyResolver#setRequiredProperties// 属性校验getEnvironment().validateRequiredProperties();// Store pre-refresh ApplicationListeners...// 监听器的初始化(兼顾可以反复刷新的IOC容器)if (this.earlyApplicationListeners == null) {this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);} else {// Reset local application listeners to pre-refresh state.this.applicationListeners.clear();this.applicationListeners.addAll(this.earlyApplicationListeners);}// Allow for the collection of early ApplicationEvents,// to be published once the multicaster is available...// 7.1.2 初始化早期事件的结合this.earlyApplicationEvents = new LinkedHashSet<>();
}

由 代码清单3 可知,初始化前的预处理阶段的大多数动作都是前置性准备,有两个步骤比较关键。

7.1.1 初始化属性配置

代码清单4AbstractApplicationContext.javaprotected void initPropertySources() {// For subclasses: do nothing by default.
}

由 代码清单4 可知,initPropertySources是一个模板方法,默认不会做任何事情,而是留给子类重写。

在 SpringBoot源码解读与原理分析(十九)IOC容器的创建与初始化 6.3.2 创建IOC容器 中提到,SpringBoot会根据已经推断好的Web类型区分创建不同的ApplicationContext落地实现类。基于Servlet的落地实现类是AnnotationConfigServletWebServerApplicationContext。

借助IDEA可以得到AnnotationConfigServletWebServerApplicationContext与AbstractApplicationContext的继承关系:

继承关系

在GenericWebApplicationContext类中重写了initPropertySources方法:

代码清单5GenericWebApplicationContext.java@Override
protected void initPropertySources() {ConfigurableEnvironment env = getEnvironment();if (env instanceof ConfigurableWebEnvironment) {((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, null);}
}
代码清单6StandardServletEnvironment.java@Override
public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {WebApplicationContextUtils.initServletPropertySources(getPropertySources(), servletContext, servletConfig);
}    

由 代码清单5、6 可知,initPropertySources方法会获取一个ConfigurableWebEnvironment,并配置当前的ServletContext。

代码清单7WebApplicationContextUtils.javapublic static void initServletPropertySources(MutablePropertySources sources,
@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {Assert.notNull(sources, "'propertySources' must not be null");String name = StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME;if (servletContext != null && sources.get(name) instanceof StubPropertySource) {// 将ServletContext当作一个属性配置源注入Environment中sources.replace(name, new ServletContextPropertySource(name, servletContext));}name = StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME;if (servletConfig != null && sources.get(name) instanceof StubPropertySource) {// 将ServletConfig当作一个属性配置源注入Environment中sources.replace(name, new ServletConfigPropertySource(name, servletConfig));}
}

由 代码清单7 可知,WebApplicationContextUtils的静态initServletPropertySources方法是将ServletContext和ServletConfig封装为PropertySource,存入Environment内置的聚合对象MutablePropertySources中。每次从Environment中获取配置属性时,实际是从MutablePropertySources中取值,而MutablePropertySources会遍历自身聚合的所有PropertySource并尝试获取指定的配置属性。

7.1.2 初始化早期事件的集合

代码清单8AbstractApplicationContext.java/** ApplicationEvents published before the multicaster setup. */
@Nullable
private Set<ApplicationEvent> earlyApplicationEvents;// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();

由 代码清单8 中的注释可以了解到,earlyApplicationEvents用于保存事件广播器初始化之前的早期事件,一旦事件广播器可用,这些保存的事件将被广播。换句话说,在监听机制可用之前,可能会产生一些事件需要广播,earlyApplicationEvents把这些事件暂存起来,等到监听机制可用再逐一广播,以确保所有监听器都监听到自己本应该监听到的事件。

7.2 初始化BeanFactory

// Tell the subclass to refresh the internal bean factory.
// 7.2 获取BeanFactory,加载所有bean的定义信息(未实例化)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
代码清单9AbstractApplicationContext.javaprotected ConfigurableListableBeanFactory obtainFreshBeanFactory() {// 刷新BeanFactoryrefreshBeanFactory();// 获取BeanFactoryreturn getBeanFactory();
}protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;

由 代码清单9 可知,初始化BeanFactory分为两步:刷新BeanFactory;获取BeanFactory。

刷新BeanFactory的refreshBeanFactory方法本身是一个抽象方法,需要子类实现。借助IDEA可得GenericApplicationContext和AbstractRefreshableApplicationContext均实现了这个方法,分别对应基于注解驱动的IOC容器和基于XML配置文件驱动的IOC容器。

7.2.1 注解驱动的refreshBeanFactory

代码清单10GenericApplicationContext.java@Override
protected final void refreshBeanFactory() throws IllegalStateException {if (!this.refreshed.compareAndSet(false, true)) {throw new IllegalStateException("GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");}this.beanFactory.setSerializationId(getId());
}

由 代码清单10 可知,基于注解驱动的refreshBeanFactory仅仅设置了BeanFactory的序列化ID。

7.2.2 XML驱动的refreshBeanFactory

由于SpringBoot已不再使用这种方式,简单了解。

代码清单11AbstractRefreshableApplicationContext.java@Override
protected final void refreshBeanFactory() throws BeansException {// 如果BeanFactory已存在,则先销毁Bean和关闭BeanFactory// 因为基于XML驱动的IOC容器是可刷新的,内部的Bean也是可以重新加载的if (hasBeanFactory()) {destroyBeans();closeBeanFactory();}try {// 创建BeanFactoryDefaultListableBeanFactory beanFactory = createBeanFactory();beanFactory.setSerializationId(getId());// 自定义配置BeanFactorycustomizeBeanFactory(beanFactory);// 解析、加载XML中定义的BeanDefinitionloadBeanDefinitions(beanFactory);this.beanFactory = beanFactory;}catch (IOException ex) {throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);}
}

7.2.3 获取BeanFactory

代码清单12:AbstractApplicationContext.javapublic abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

由 代码清单12 可知,getBeanFactory方法是一个模板方法,由子类实现。

代码清单13:GenericApplicationContext.javaprivate final DefaultListableBeanFactory beanFactory;
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {return this.beanFactory;
}

由 代码清单13 可知,在子类GenericApplicationContext中实现了这个方法,返回一个DefaultListableBeanFactory对象。也就是说,此时BeanFactory的落地实现就是一个DefaultListableBeanFactory。

7.3 BeanFactory的预处理配置

// Prepare the bean factory for use in this context.
// 7.3 BeanFactory的预处理配置
prepareBeanFactory(beanFactory);
代码清单14AbstractApplicationContext.javaprotected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// Tell the internal bean factory to use the context's class loader etc.// 设置BeanFactory的类加载器、表达式解析器等beanFactory.setBeanClassLoader(getClassLoader());beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));// Configure the bean factory with context callbacks.// 7.3.1 配置一个可回调注入ApplicationContext的BeanPostProcessorbeanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));// 忽略几种依赖接口beanFactory.ignoreDependencyInterface(EnvironmentAware.class);beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);beanFactory.ignoreDependencyInterface(MessageSourceAware.class);beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);// BeanFactory interface not registered as resolvable type in a plain factory.// MessageSource registered (and found for autowiring) as a bean.// 7.3.2 自动注入的支持beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);// Register early post-processor for detecting inner beans as ApplicationListeners.// 7.3.3 配置一个可加载所有监听器的组件beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));// Detect a LoadTimeWeaver and prepare for weaving, if found.// LoadTimeWeaver的支持if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));// Set a temporary ClassLoader for type matching.beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}// Register default environment beans.// 向BeanFactory中注册Environment、系统配置属性、系统环境的信息// Environment本身对于BeanFactory来讲也是一个Beanif (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());}if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());}if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());}
}

7.3.1 ApplicationContextAwareProcessor

7.3.1.1 ApplicationContextAwareProcessor的作用
代码清单15ApplicationContextAwareProcessor.java@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {// 如果被处理的Bean不是指定的Aware类型接口,则不予处理if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){return bean;}// ...// 执行Aware接口的回调注入invokeAwareInterfaces(bean);return bean;
}private void invokeAwareInterfaces(Object bean) {// 判断实现的接口,进行强转并调用setter方法if (bean instanceof EnvironmentAware) {((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());}if (bean instanceof EmbeddedValueResolverAware) {((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);}if (bean instanceof ResourceLoaderAware) {((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);}if (bean instanceof ApplicationEventPublisherAware) {((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);}if (bean instanceof MessageSourceAware) {((MessageSourceAware) bean).setMessageSource(this.applicationContext);}if (bean instanceof ApplicationContextAware) {((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);}
}

由 代码清单15 可知,ApplicationContextAwareProcessor实现了BeanPostProcessor接口,它会判断一个bean对象所属类是实现了指定的内置Aware系列接口。只要检测到bean对象所属类有一个Aware系列接口实现,就会尝试将其强转为对应的Aware接口,并调接口对应的setter方法完成Aware接口的回调注入。

7.3.1.2 ignoreDependencyInterface

从上面的分析可知,Aware系列接口的注入使用的是BeanPostProcessor注入的方式,因此使用ignoreDependencyInterface是为了放弃这些Aware接口在BeanFactory中实现的自动依赖注入,

7.3.2 自动注入的支持

处理完Aware类型的接口后,接下来是向BeanFactory注册几个接口类型与指定对象的映射关系。

代码清单16AbstractApplicationContext.java// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
代码清单17DefaultListableBeanFactory.javaprivate final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);
@Override
public void registerResolvableDependency(Class<?> dependencyType, @Nullable Object autowiredValue) {Assert.notNull(dependencyType, "Dependency type must not be null");if (autowiredValue != null) {if (!(autowiredValue instanceof ObjectFactory || dependencyType.isInstance(autowiredValue))) {throw new IllegalArgumentException("Value [" + autowiredValue +"] does not implement specified dependency type [" + dependencyType.getName() + "]");}this.resolvableDependencies.put(dependencyType, autowiredValue);}
}

由 代码清单16、17 可知,registerResolvableDependency方法的作用是使BeanFactory遇到指定类型的对象需要注入时,直接使用映射的对象进行注入。Map集合resolvableDependencies就是负责存储指定类型和对应实现类的集合,后续进行依赖注入时,遇到指定的类型就可以直接从这个Map集合中提取。

7.3.3 ApplicationListenerDetector

// Register early post-processor for detecting inner beans as ApplicationListeners.
// 7.3.3 配置一个可加载所有监听器的组件
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

处理完依赖类型后,prepareBeanFactory方法会向BeanFactory注册一个后置处理器ApplicationListenerDetector。

BeanPostProcessorthat detects beans which implement the ApplicationListenerinterface. This catches beans that can’t reliably be detected by getBeanNamesForTypeand related operations which only work against top-level beans.
ApplicationListenerDetector是一个用于检测实现了ApplicationListener接口的Bean的后置处理器,它可以捕获通过getBeanNamesForType方法以及仅对顶级Bean有效的相关操作无法可靠地检测到的Bean。

由javadoc可知,ApplicationListenerDetector的作用是在bean对象初始化阶段检测当前bean对象是否是ApplicationListener,如果是则会进行一些额外的处理:将该bean对象加入到ApplicationContext的监听器集合中。

代码清单18ApplicationListenerDetector.java@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {if (bean instanceof ApplicationListener) {// potentially not detected as a listener by getBeanNamesForType retrievalBoolean flag = this.singletonNames.get(beanName);if (Boolean.TRUE.equals(flag)) {// singleton bean (top-level or inner): register on the fly// 如果当前bean对象是ApplicationListener且是一个单实例对象// 则将该bean对象加入到ApplicationContext的监听器集合中this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);}else if (Boolean.FALSE.equals(flag)) {if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {// inner bean with other scope - can't reliably process eventslogger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +"but is not reachable for event multicasting by its containing ApplicationContext " +"because it does not have singleton scope. Only top-level listener beans are allowed " +"to be of non-singleton scope.");}this.singletonNames.remove(beanName);}}return bean;
}

另外,ApplicationListenerDetector实现了DestructionAwareBeanPostProcessor接口,说明其还有对bean对象销毁阶段的处理(postProcessBeforeDestruction方法)。

代码清单19ApplicationListenerDetector.javaclass ApplicationListenerDetector implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor {@Overridepublic void postProcessBeforeDestruction(Object bean, String beanName) {if (bean instanceof ApplicationListener) {try {// 将监听器类型的bean对象逐个从事件广播器中移除ApplicationEventMulticaster multicaster = this.applicationContext.getApplicationEventMulticaster();multicaster.removeApplicationListener((ApplicationListener<?>) bean);multicaster.removeApplicationListenerBean(beanName);}catch (IllegalStateException ex) {// ApplicationEventMulticaster not initialized yet - no need to remove a listener}}}
}

由 代码清单19 可知,ApplicationListenerDetector会在bean对象销毁阶段将监听器类型的bean对象逐个从事件广播器中移除。

至此,IOC容器的刷新完成了前面三步,分别是初始化前的预处理、初始化BeanFactory以及BeanFactory的预处理配置。

本节完,更多内容请查阅分类专栏:SpringBoot源码解读与原理分析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2777097.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Spring基础 - Spring简单例子引入Spring要点

Spring基础 - Spring简单例子引入Spring要点 设计一个Spring的Hello World 设计一个查询用户的案例的两个需求&#xff0c;来看Spring框架帮我们简化了什么开发工作 pom依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"htt…

FastJson、Jackson使用AOP切面进行日志打印异常

FastJson、Jackson使用AOP切面进行日志打印异常 一、概述 1、问题详情 使用FastJson、Jackson进行日志打印时分别包如下错误&#xff1a; 源码&#xff1a; //fastjon log.info("\nRequest Info :{} \n"&#xff0c; JSON.toJSONString(requestInfo)); //jackson …

106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)

题目描述 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 题目示例 输入&#xff1a;inorder [9,3,15,20,7], postorder [9,15,7,20,3] 输出&a…

【正式】今年第一篇CSDN(纯技术教学)

一、文件上传简介 文件上传漏洞是指用户上传了一个可执行的脚本文件&#xff08;木马、病毒、恶意脚本、webshell等&#xff09;&#xff0c;并通过此脚本文件获得了执行服务器端命令的能力。上传点一般出现在头像、导入数据、上传压缩包等地方&#xff0c;由于程序对用户上传…

《Git 简易速速上手小册》第10章:未来趋势与扩展阅读(2024 最新版)

文章目录 10.1 Git 与开源社区10.1.1 基础知识讲解10.1.2 重点案例&#xff1a;Python 社区使用 Git10.1.3 拓展案例 1&#xff1a;Git 在大型开源项目中的角色10.1.4 拓展案例 2&#xff1a;支持开源项目的 Git 托管平台 10.2 新兴技术与 Git 的整合10.2.1 基础知识讲解10.2.2…

《剑指Offer》笔记题解思路技巧优化 Java版本——新版leetcode_Part_1

《剑指Offer》笔记&题解&思路&技巧&优化_Part_1 &#x1f60d;&#x1f60d;&#x1f60d; 相知&#x1f64c;&#x1f64c;&#x1f64c; 相识&#x1f622;&#x1f622;&#x1f622; 开始刷题1. LCR 120. 寻找文件副本——数组中重复元素2. LCR 121. 寻找目…

Amazon Dynamo学习总结

目录 一、Amazon Dynamo的问世 二、Amazon Dynamo主要技术概要 三、数据划分算法 四、数据复制 五、版本控制 六、故障处理 七、成员和故障检测 一、Amazon Dynamo的问世 Amazon Dynamo是由亚马逊在2007年开发的一种高度可扩展和分布式的键值存储系统&#xff0c;旨在解…

Android13多媒体框架概览

Android13多媒体框架概览 Android 多媒体框架 Android 多媒体框架旨在为 Java 服务提供可靠的接口。它是一个系统&#xff0c;包括多媒体应用程序、框架、OpenCore 引擎、音频/视频/输入的硬件设备&#xff0c;输出设备以及一些核心动态库&#xff0c;比如 libmedia、libmedi…

ARM PAC/BTI/MTE三剑客精讲与实战

一、PAC指针认证精讲与实战 思考 1、什么是栈溢出攻击&#xff1f;什么是代码重用攻击&#xff1f;区别与联系&#xff1f; 2、栈溢出攻击的软&硬件缓解技术有哪些&#xff1f;在TF-A&OPTEE上的应用&#xff1f; 3、什么是ROP攻击&#xff1f;对ROP攻击的缓解技术&…

Redis -- 数据库管理

目录 前言 切换数据库(select) 数据库中key的数量&#xff08;dbsize&#xff09; 清除数据库&#xff08;flushall flushdb&#xff09; 前言 MySQL有一个很重要的概念&#xff0c;那就是数据库database&#xff0c;一个MySQL里面有很多个database&#xff0c;一个datab…

龙芯开启ssh服务——使用Putty连接

本文采用龙芯3A6000处理器&#xff0c;Loongnix操作系统。 为了能使用其他电脑远程操控龙芯电脑&#xff0c;需要打开loongnix的ssh服务&#xff0c;并在其他电脑里使用putty连接loongnix。 1 修改ssh配置文件 命令行输入&#xff1a; sudo vim /etc/ssh/sshd_config按下i插…

【初中生讲机器学习】6. 分类算法中常用的模型评价指标有哪些?here!

创建时间&#xff1a;2024-02-07 最后编辑时间&#xff1a;2024-02-09 作者&#xff1a;Geeker_LStar 你好呀~这里是 Geeker_LStar 的人工智能学习专栏&#xff0c;很高兴遇见你~ 我是 Geeker_LStar&#xff0c;一名初三学生&#xff0c;热爱计算机和数学&#xff0c;我们一起加…

HACKTHEBOX通关笔记——mango(退役)

信息收集 端口扫描 ┌──(root㉿kali)-[~] └─# nmap -sC -sV -A -p- --min-rate10000 10.129.229.185 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-01-31 20:44 EST Warning: 10.129.229.185 giving up on port because retransmission cap hit (10). Nmap scan …

方案分享:F5怎么样应对混合云网络安全?

伴随着云计算走入落地阶段&#xff0c;企业的云上业务规模增长迅猛。具有部署灵活、成本低、最大化整合现有资产、促进业务创新等优点的混合云逐渐成为企业选择的部署方式。与此同时&#xff0c;安全运营的复杂度进一步提高。比如安全堆栈越来越复杂、多云基础设施和应用添加网…

攻防世界——re2-cpp-is-awesome

64位 我先用虚拟机跑了一下这个程序&#xff0c;结果输出一串字符串flag ——没用 IDA打开后 F5也没有什么可看的 那我们就F12查看字符串找可疑信息 这里一下就看见了 __int64 __fastcall main(int a1, char **a2, char **a3) {char *v3; // rbx__int64 v4; // rax__int64 v…

【机房预约系统(C++版)】

一、机房预约系统需求 1.1、系统简介 学校现有几个规格不同的机房&#xff0c;由于使用时经常出现“撞车“现象,现开发一套机房预约系统&#xff0c;解决这一问题。 1.2、身份简介 分别有三种身份使用该程序学生代表:申请使用机房教师:审核学生的预约申请管理员:给学生、教…

Git分支常用指令

目录 1 git branch 2 git branch xx 3 git checkout xx 4 git checkout -b xx 5 git branch -d xx 6 git branch -D xx 7 git merge xx(含快进模式和冲突解决的讲解) 注意git-log: 1 git branch 作用&#xff1a;查看分支 示例&#xff1a; 2 git branch xx 作用&a…

第二节课[Demo]作业

基础作业 使用 InternLM-Chat-7B 模型生成 300 字的小故事 user avatar 你是一个精通isekai的勇者&#xff0c;现在需要你讲述一段清新脱俗的异世界日常故事&#xff0c;字数300字以上robot avatar 在一个普通的早晨&#xff0c;我像往常一样起床、洗漱、吃早餐。但是&#xf…

第二十六回 母夜叉孟州道卖人肉 武都头十字坡遇张青-Ubuntu 防火墙ufw配置

武松到县里投案&#xff0c;县官看武松是个汉子&#xff0c;就把诉状改成&#xff1a;武松与嫂一时斗殴杀死&#xff0c;后西门庆前来&#xff0c;两人互殴&#xff0c;打死西门庆。上报东平府。东平府尹也可怜武松&#xff0c;从轻发落&#xff0c;最后判了个&#xff1a;脊杖…

【超高效!保护隐私的新方法】针对图像到图像(l2l)生成模型遗忘学习:超高效且不需要重新训练就能从生成模型中移除特定数据

针对图像到图像生成模型遗忘学习&#xff1a;超高效且不需要重新训练就能从生成模型中移除特定数据 提出背景如何在不重训练模型的情况下从I2I生成模型中移除特定数据&#xff1f; 超高效的机器遗忘方法子问题1: 如何在图像到图像&#xff08;I2I&#xff09;生成模型中进行高效…