【Spring】AbstractApplicationContext源码解读

这个类源码一打开,我滴妈有一种我不卷了,我送外卖去了的感觉1500行····

但是还是对你自己说 坚持坚持再坚持。35岁再送外卖也不迟。

这里我们先看这个抽象类的注释:

Abstract implementation of the ApplicationContext interface. Doesn't mandate the type of storage used for configuration; simply implements common context functionality. Uses the Template Method design pattern, requiring concrete subclasses to implement abstract methods.
In contrast to a plain BeanFactory, an ApplicationContext is supposed to detect special beans defined in its internal bean factory: Therefore, this class automatically registers BeanFactoryPostProcessors, BeanPostProcessors, and ApplicationListeners which are defined as beans in the context.
A MessageSource may also be supplied as a bean in the context, with the name "messageSource"; otherwise, message resolution is delegated to the parent context. Furthermore, a multicaster for application events can be supplied as an "applicationEventMulticaster" bean of type ApplicationEventMulticaster in the context; otherwise, a default multicaster of type SimpleApplicationEventMulticaster will be used.
Implements resource loading by extending DefaultResourceLoader. Consequently treats non-URL resource paths as class path resources (supporting full class path resource names that include the package path, e.g. "mypackage/myresource.dat"), unless the getResourceByPath method is overridden in a subclass.
Since:
January 21, 2001
See Also:
refreshBeanFactory, getBeanFactory, BeanFactoryPostProcessor, org.springframework.beans.factory.config.BeanPostProcessor, ApplicationEventMulticaster, ApplicationListener, MessageSource
Author:
Rod Johnson, Juergen Hoeller, Mark Fisher, Stephane Nicoll, Sam Brannen, Sebastien Deleuze, Brian Clozel

翻译:

ApplicationContext接口的抽象实现。不强制要求用于配置的存储类型;简单地实现通用上下文功能。使用模板方法设计模式需要具体的子类来实现抽象方法
与普通BeanFactory相比,ApplicationContext应该检测其内部bean工厂中定义的特殊bean:因此,此类自动注册BeanFactoryPostProcessorsBeanPostProcessorsApplicationListeners,它们在上下文中定义为bean。
MessageSource也可以在上下文中作为bean提供,名称为“MessageSource”;否则,消息解析将委托给父上下文。

此外,用于应用程序事件的多主机可以作为上下文中ApplicationEventMultimaster类型的“applicationEventMultimaster”bean提供;

否则,将使用类型为SimpleApplicationEventMulticaster的默认多播器。
通过扩展DefaultResourceLoader实现资源加载。

因此,将非URL资源路径视为类路径资源(支持包括包路径的完整类路径资源名称,例如“mypackage/myresource.dat”),除非在子类中重写getResourceByPath方法。

这里需要对标红的内容有个基本的印象,后面很多知识围绕这些名称展开。

1.源码阅读(以下为完整源码):

1.1四个类常量属性

看不懂没事,先不管

工厂中MessageSource bean的名称。如果没有提供,则将消息解析委派给父级。
public static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource";工厂中的LifecycleProcessor bean的名称。如果没有提供,则使用DefaultLifecycleProcessor。
public static final String LIFECYCLE_PROCESSOR_BEAN_NAME = "lifecycleProcessor";工厂中ApplicationEventMulticastbean的名称。如果没有提供,则使用默认的SimpleApplicationEventMultimaster。
public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";由spring.spel.ignore系统属性控制的布尔标志,该属性指示spring忽略spel,即不初始化spel基础结构。
默认值为“false”。
private static final boolean shouldIgnoreSpel = SpringProperties.getFlag("spring.spel.ignore");

1.2.一个静态代码块

看不懂继续跳过

//急切地加载ContextClosedEvent类以避免奇怪的类加载器问题
//关于WebLogic 8.1中的应用程序关闭。(达斯汀·伍兹报道)
static {// Eagerly load the ContextClosedEvent class to avoid weird classloader issues// on application shutdown in WebLogic 8.1. (Reported by Dustin Woods.)ContextClosedEvent.class.getName();
}

1.3.日志打印

/** Logger used by this class. Available to subclasses. */
protected final Log logger = LogFactory.getLog(getClass());

1.4.唯一标识这个上下文。这个对象。

/** Unique id for this context, if any. */
private String id = ObjectUtils.identityToString(this);/** Display name. */
private String displayName = ObjectUtils.identityToString(this);

1.5.两个接口引用,应用上下文接口,可配置环境接口,这里先跳过。有个印象

/** Parent context. */
@Nullable
private ApplicationContext parent;/** Environment used by this context. */
@Nullable
private ConfigurableEnvironment environment;

1.6.BeanFactoryPostProcessor数组

这里有个BeanFactoryPostProcessor数组,一个bean工厂的后置处理器数组。这里很重要,我们先对BeanFactoryPostProcessor这个名称有个记忆。如果有一点aop动态代理基础的朋友,应该可以联想到前置处理器和后置处理器的东西了。这里先知道这里有个数组。

/** BeanFactoryPostProcessors to apply on refresh. */
private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>();

1.7.状态信息

这里主要是一些对这个上下文定义的一些状态信息。

上下文启动时的系统时间(以毫秒为单位)。
private long startupDate;上下文当前是否处于活动状态的标志。
private final AtomicBoolean active = new AtomicBoolean();指示此上下文是否已关闭的标志。
private final AtomicBoolean closed = new AtomicBoolean();“刷新”和“销毁”的同步监视器。
private final Object startupShutdownMonitor = new Object();

1.8.JVM相关

先不管

对JVM关闭回调的引用(如果已注册)。
@Nullable
private Thread shutdownHook;

1.9.上下文的一些高级应用

看不懂没事,先跳过

此上下文使用的ResourcePatternResolver。
private ResourcePatternResolver resourcePatternResolver;LifecycleProcessor,用于在此上下文中管理bean的生命周期。
@Nullable
private LifecycleProcessor lifecycleProcessor;我们将此接口的实现委托给MessageSource。
@Nullable
private MessageSource messageSource;

事件发布中使用的帮助程序类。
@Nullable
private ApplicationEventMulticaster applicationEventMulticaster;应用程序启动指标。
private ApplicationStartup applicationStartup = ApplicationStartup.DEFAULT;静态指定的侦听器。
private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();在刷新前已注册的本地侦听器。
@Nullable
private Set<ApplicationListener<?>> earlyApplicationListeners;在多主机安装之前发布的ApplicationEvents。
@Nullable
private Set<ApplicationEvent> earlyApplicationEvents;

1.10. 两个构造方法

不用管

/*** 创建一个没有父级的新AbstractApplicationContext。*/
public AbstractApplicationContext() {this.resourcePatternResolver = getResourcePatternResolver();
}

/*** 使用给定的父上下文创建一个新的AbstractApplicationContext。* @param parent the parent context*/
public AbstractApplicationContext(@Nullable ApplicationContext parent) {this();setParent(parent);
}

1.11.一堆set,get方法

先不管

//---------------------------------------------------------------------
// Implementation of ApplicationContext interface
//---------------------------------------------------------------------/*** Set the unique id of this application context.* <p>Default is the object id of the context instance, or the name* of the context bean if the context is itself defined as a bean.* @param id the unique id of the context*/
@Override
public void setId(String id) {this.id = id;
}@Override
public String getId() {return this.id;
}

@Override
public String getApplicationName() {return "";
}

/*** Set a friendly name for this context.* Typically done during initialization of concrete context implementations.* <p>Default is the object id of the context instance.*/
public void setDisplayName(String displayName) {Assert.hasLength(displayName, "Display name must not be empty");this.displayName = displayName;
}

/*** Return a friendly name for this context.* @return a display name for this context (never {@code null})*/
@Override
public String getDisplayName() {return this.displayName;
}/*** Return the parent context, or {@code null} if there is no parent* (that is, this context is the root of the context hierarchy).*/
@Override
@Nullable
public ApplicationContext getParent() {return this.parent;
}/*** Set the {@code Environment} for this application context.* <p>Default value is determined by {@link #createEnvironment()}. Replacing the* default with this method is one option but configuration through {@link* #getEnvironment()} should also be considered. In either case, such modifications* should be performed <em>before</em> {@link #refresh()}.* @see org.springframework.context.support.AbstractApplicationContext#createEnvironment*/
@Override
public void setEnvironment(ConfigurableEnvironment environment) {this.environment = environment;
}/*** Return the {@code Environment} for this application context in configurable* form, allowing for further customization.* <p>If none specified, a default environment will be initialized via* {@link #createEnvironment()}.*/
@Override
public ConfigurableEnvironment getEnvironment() {if (this.environment == null) {this.environment = createEnvironment();}return this.environment;
}/*** Create and return a new {@link StandardEnvironment}.* <p>Subclasses may override this method in order to supply* a custom {@link ConfigurableEnvironment} implementation.*/
protected ConfigurableEnvironment createEnvironment() {return new StandardEnvironment();
}/*** Return this context's internal bean factory as AutowireCapableBeanFactory,* if already available.* @see #getBeanFactory()*/
@Override
public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException {return getBeanFactory();
}/*** Return the timestamp (ms) when this context was first loaded.*/
@Override
public long getStartupDate() {return this.startupDate;
}/*** Publish the given event to all listeners.* <p>Note: Listeners get initialized after the MessageSource, to be able* to access it within listener implementations. Thus, MessageSource* implementations cannot publish events.* @param event the event to publish (may be application-specific or a* standard framework event)*/
@Override
public void publishEvent(ApplicationEvent event) {publishEvent(event, null);
}/*** Publish the given event to all listeners.* <p>Note: Listeners get initialized after the MessageSource, to be able* to access it within listener implementations. Thus, MessageSource* implementations cannot publish events.* @param event the event to publish (may be an {@link ApplicationEvent}* or a payload object to be turned into a {@link PayloadApplicationEvent})*/
@Override
public void publishEvent(Object event) {publishEvent(event, null);
}

/*** 将给定的事件发布给所有侦听器。* @param event the event to publish (may be an {@link ApplicationEvent}* or a payload object to be turned into a {@link PayloadApplicationEvent})* @param eventType the resolved event type, if known* @since 4.2*/
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {Assert.notNull(event, "Event must not be null");// Decorate event as an ApplicationEvent if necessaryApplicationEvent applicationEvent;if (event instanceof ApplicationEvent) {applicationEvent = (ApplicationEvent) event;}else {applicationEvent = new PayloadApplicationEvent<>(this, event);if (eventType == null) {eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();}}// Multicast right now if possible - or lazily once the multicaster is initializedif (this.earlyApplicationEvents != null) {this.earlyApplicationEvents.add(applicationEvent);}else {getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);}// Publish event via parent context as well...if (this.parent != null) {if (this.parent instanceof AbstractApplicationContext) {((AbstractApplicationContext) this.parent).publishEvent(event, eventType);}else {this.parent.publishEvent(event);}}
}/*** Return the internal ApplicationEventMulticaster used by the context.* @return the internal ApplicationEventMulticaster (never {@code null})* @throws IllegalStateException if the context has not been initialized yet*/
ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {if (this.applicationEventMulticaster == null) {throw new IllegalStateException("ApplicationEventMulticaster not initialized - " +"call 'refresh' before multicasting events via the context: " + this);}return this.applicationEventMulticaster;
}@Override
public void setApplicationStartup(ApplicationStartup applicationStartup) {Assert.notNull(applicationStartup, "applicationStartup should not be null");this.applicationStartup = applicationStartup;
}@Override
public ApplicationStartup getApplicationStartup() {return this.applicationStartup;
}/*** Return the internal LifecycleProcessor used by the context.* @return the internal LifecycleProcessor (never {@code null})* @throws IllegalStateException if the context has not been initialized yet*/
LifecycleProcessor getLifecycleProcessor() throws IllegalStateException {if (this.lifecycleProcessor == null) {throw new IllegalStateException("LifecycleProcessor not initialized - " +"call 'refresh' before invoking lifecycle methods via the context: " + this);}return this.lifecycleProcessor;
}/*** Return the ResourcePatternResolver to use for resolving location patterns* into Resource instances. Default is a* {@link org.springframework.core.io.support.PathMatchingResourcePatternResolver},* supporting Ant-style location patterns.* <p>Can be overridden in subclasses, for extended resolution strategies,* for example in a web environment.* <p><b>Do not call this when needing to resolve a location pattern.</b>* Call the context's {@code getResources} method instead, which* will delegate to the ResourcePatternResolver.* @return the ResourcePatternResolver for this context* @see #getResources* @see org.springframework.core.io.support.PathMatchingResourcePatternResolver*/
protected ResourcePatternResolver getResourcePatternResolver() {return new PathMatchingResourcePatternResolver(this);
}//---------------------------------------------------------------------
// Implementation of ConfigurableApplicationContext interface
//---------------------------------------------------------------------/*** Set the parent of this application context.* <p>The parent {@linkplain ApplicationContext#getEnvironment() environment} is* {@linkplain ConfigurableEnvironment#merge(ConfigurableEnvironment) merged} with* this (child) application context environment if the parent is non-{@code null} and* its environment is an instance of {@link ConfigurableEnvironment}.* @see ConfigurableEnvironment#merge(ConfigurableEnvironment)*/
@Override
public void setParent(@Nullable ApplicationContext parent) {this.parent = parent;if (parent != null) {Environment parentEnvironment = parent.getEnvironment();if (parentEnvironment instanceof ConfigurableEnvironment) {getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);}}
}@Override
public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");this.beanFactoryPostProcessors.add(postProcessor);
}/*** Return the list of BeanFactoryPostProcessors that will get applied* to the internal BeanFactory.*/
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {return this.beanFactoryPostProcessors;
}@Override
public void addApplicationListener(ApplicationListener<?> listener) {Assert.notNull(listener, "ApplicationListener must not be null");if (this.applicationEventMulticaster != null) {this.applicationEventMulticaster.addApplicationListener(listener);}this.applicationListeners.add(listener);
}/*** Return the list of statically specified ApplicationListeners.*/
public Collection<ApplicationListener<?>> getApplicationListeners() {return this.applicationListeners;
}

1.12 Refresh()

他来了。这个方法非常的关键

这个方法是ConfigurableApplicationContext接口中定义的,并在本抽象类进行了实现,在这个接口中,它对这个方法的定义如下:

加载刷新配置的持久表示,它可能来自基于Java的配置、XML文件、属性文件、关系数据库模式或其他格式。
由于这是一种启动方法,如果失败,它应该销毁已经创建的singleton,以避免挂起资源。换句话说,在调用此方法之后,应该实例化所有Bean或不实例化singleton。

这个方法的意思就是

@Override
public void refresh() throws BeansException, IllegalStateException {
//锁住启动监视器同步器,避免同一时刻多次执行refresh操作synchronized (this.startupShutdownMonitor) {StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");//准备此上下文以进行刷新。prepareRefresh();//告诉子类刷新内部bean工厂。ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();//准备bean工厂以便在此上下文中使用。prepareBeanFactory(beanFactory);try {// 允许在上下文子类中对bean工厂进行后处理。postProcessBeanFactory(beanFactory);StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");// 调用在上下文中注册为bean的工厂处理器。invokeBeanFactoryPostProcessors(beanFactory);// 注册拦截bean创建的bean处理器。registerBeanPostProcessors(beanFactory);beanPostProcess.end();// 初始化此上下文的消息源。initMessageSource();//初始化此上下文的事件多播器。initApplicationEventMulticaster();//初始化特定上下文子类中的其他特殊bean。onRefresh();//检查侦听器bean并注册它们。registerListeners();// 实例化所有剩余的(非惰性init)singleton。finishBeanFactoryInitialization(beanFactory);// 最后一步:发布相应的事件。finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// 销毁已创建的singleton以避免挂起资源。destroyBeans();// 重置“活动”标志。cancelRefresh(ex);//向调用方传播异常。throw ex;}finally {// 重置Spring核心中的常见内省缓存,因为我们可能不再需要单例bean的元数据了resetCommonCaches();contextRefresh.end();}}
}

 这个方法就是一个完整的Bean的生命周期操作,学习Bean的生命周期,也就是对这个方法的解读。

先来一行一行的看一遍:

表示当前加载或刷新bean进行到哪一步,不重要

StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

做一些准备工作,比如切换上下文执行状态,打印日志,验证属性有效性,注册一些事件监听器等。不重要

prepareRefresh();

内部:

protected void prepareRefresh() {// 切换为活跃状态.this.startupDate = System.currentTimeMillis();this.closed.set(false);this.active.set(true);//打印正在执行refresh操作的上下文日志if (logger.isDebugEnabled()) {if (logger.isTraceEnabled()) {logger.trace("Refreshing " + this);}else {logger.debug("Refreshing " + getDisplayName());}}// 初始化上下文环境中的任何占位符属性源。在这个抽象类中没有对这个方法进行实现。initPropertySources();// 验证标记为必需的所有属性是否可解析。PS:这里你回想一下有些类中的属性,我们需要加上Required注解来表示这个属性必须被加载。// 请参阅ConfigurationPropertyResolver#setRequiredPropertiesgetEnvironment().validateRequiredProperties();// 存储refresh操作之前的事件监听器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);}// 允许收集早期ApplicationEvents,以便在多播主机可用后发布this.earlyApplicationEvents = new LinkedHashSet<>();
}

让子类刷新内部bean工厂。并且有旧的工厂时,销毁旧工厂,重新加载新工厂,并获取bean的定义,从注解或者xml中获取bean的定义。返回生产这些bean的工厂对象。

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
1.12.1 onRefresh()

这个方法在这个抽象类中没有实现

/*** Template method which can be overridden to add context-specific refresh work.* Called on initialization of special beans, before instantiation of singletons.* <p>This implementation is empty.* @throws BeansException in case of errors* @see #refresh()*/
protected void onRefresh() throws BeansException {// For subclasses: do nothing by default.
}

这个是一个模版设计模式。虽然在这个抽象类中没有实现,我们找到一个实现了这个抽象类的类来说明这个抽象方法可以做哪些事:

 这个onRefresh()方法在spring中有五个类实现了这个方法。

我们看看这个类:ServletWebServerApplicationContext

ServletWeb服务器应用上下文、熟悉吧?不熟悉的话我们看看他做了什么

进入createWebServer,创建web服务器

进入这段代码ServletWebServerFactory factory = getWebServerFactory();

获取web服务器工厂

进入:String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);

这段代码意思是从ServletWebServerFactory这个接口的类型中获取bean的name,

ServletWebServerFactory接口代码:

那么我们来看看这个ServletWebServerFactory.class接口到底有哪些类型:

!!!Tomcat的工厂。!!!Jetty工厂。!!!Undertow

 Springboot我们知道默认内置了Tomcat,当然,也可以使用其他的web服务器,这里就是一个模版设计模式。通过实现抽象类中的方法,在应用启动中,运行用户自定义的启动逻辑。这里这个类自定义的启动逻辑就是去加载运行一个tomcat服务器。

本博客是AbstractApplicationContext的源码解析,spring的基础代码跟你具体业务是没有关系的,因此抽象应用上下文抽象类,实际是做的事就是加载某个应用的上下文,加载应用的上下文所依赖的bean的工厂对象, 加载bean的对象等等功能,还有一些事件监听器的调用。比如你在应用启动的时候注册了事件监听器,那么应用启动成功后,会给你发送一个事件触发的操作。

然后具体应用的业务逻辑实现在onfresh中去完成。

1.13 BeanPostProcessors

前文提到本抽象类中会做一些BeanPostProcessors的注册。那么这部分代码到底做了什么工作我们来看看。

我们先看看什么是BeanPostProcessors

 注释翻译:

工厂回调,允许对新的bean实例进行自定义修改——例如,检查标记接口或用代理包装bean。
通常,通过标记接口等填充bean的后处理器将实现postProcessBeforeInitialization,而用代理封装bean的后处理程序通常将实现postProcessAfterInitialization
登记
ApplicationContext可以在其bean定义中自动检测BeanPostProcessor bean,并将这些后处理器应用于随后创建的任何bean。普通BeanFactory允许对后处理器进行编程注册,将它们应用于通过bean工厂创建的所有bean。
在ApplicationContext中自动检测到的BeanPostProcessor bean将根据org.springframework.core进行排序。PriorityOrdered和org.springframework.core。有序语义。相反,以编程方式向BeanFactory注册的BeanPostProcessor bean将按注册顺序应用;对于编程注册的后处理器,通过实现PriorityOrdered或Ordered接口表达的任何排序语义都将被忽略。此外,BeanPostProcessor bean没有考虑@Order注释。

我们可以理解为,既然名字叫bean的后置处理器。那么一定是对bean进行功能的增强,那么我们可以想起AOP动态代理就是对对象功能的增强。那么这里一定会用到AOP。我们继续往下看

postProcessAfterInitialization这个接口方法在类中AbstractAutoProxyCreator进行了实现

 

或者抽象类:AbstractAdvisingBeanPostProcessor

 这两个类的调用链中,最后都会指向

proxyFactory.getProxy(classLoader);

 

 

 看到这里!立马想到AOP动态代理的两种方式JDK和Cglib。

读完了依赖~我很快就离开

现在我们知道并理解为,Bean的后置处理器BeanPostProcessors的相关注册其实就是在抽象应用上下文中去使用AOP去加载注册bean的增强类,以便后续的使用。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

docker 修改运行容器环境变量

文章目录 前言第一步&#xff1a;查看Docker Root目录第二步&#xff1a;查到容器的长id&#xff08;container id&#xff09;第三步&#xff1a;停止容器第四步&#xff1a;编辑修改环境变量env第五步&#xff1a;重载服务的配置文件第六步&#xff1a;重启docker 总结 前言 …

力扣416. 分割等和子集

Problem: 416. 分割等和子集 文章目录 题目描述思路解题方法复杂度Code 题目描述 思路 该题目可以归类为0-1背包问题&#xff0c;具体到细节可以再归纳为背包是否装满问题 1.首先判断数组元素和的奇偶性&#xff08;奇数则不能划分&#xff09; 2.我们定义一个二维布尔类型数组…

【opencv】opencv透视变换和ocr识别实验

实验环境&#xff1a;anaconda、jupyter notebook 实验用到的包opencv、numpy、matplotlib、tesseract 一、opencv透视变换 原图 图片是我拍的耳机说明书&#xff0c;哈哈哈哈&#xff0c;你也可以使用自己拍的照片&#xff0c;最好是英文内容&#xff0c;tesseract默认识别英…

iOS Xcode Debug View Hierarchy 查看视图层级结构

前言 我们难免会遇到接手别人项目的情况&#xff0c;让你去改他遗留的问题&#xff0c;想想都头大&#xff0c;&#x1f602;可是也不得不面对。作为开发者只要让我们找到出问题的代码文件&#xff0c;我们就总有办法去解决它&#xff0c;那么如何快速定位问题对应的代码文件呢…

FullCalendar日历组件集成实战(4)

背景 有一些应用系统或应用功能&#xff0c;如日程管理、任务管理需要使用到日历组件。虽然Element Plus也提供了日历组件&#xff0c;但功能比较简单&#xff0c;用来做数据展现勉强可用。但如果需要进行复杂的数据展示&#xff0c;以及互动操作如通过点击添加事件&#xff0…

python如何做一个服务器fastapi 和flask

用 fastapi 方式的话 from fastapi import FastAPIapp FastAPI()app.get("/api") def index():return "hello world"然后需要安装 uvicorn 并执行下面的命令 uvicorn server:app --port 8000 --reload最终 如果是用 flask 直接写下面的代码 # -*- cod…

IP代理网络协议介绍

在IP代理页面上&#xff0c;存在HTTP/HTTPS/Socks5三种协议。它们都是客户端与服务器之间交互的协议。 HTTP HTTP又称之为超文本传输协议&#xff0c;在因特网使用范围广泛。它是一种请求/响应模型&#xff0c;客户端向服务器发送请求&#xff0c;服务器解析请求后对客户端作出…

20240514基于深度学习的弹性超材料色散关系预测与结构逆设计

论文&#xff1a;Dispersion relation prediction and structure inverse design of elastic metamaterials via deep learning DOI&#xff1a;https://doi.org/10.1016/j.mtphys.2022.100616 1、摘要 精心设计的超材料结构给予前所未有的性能&#xff0c;保证了各种各样的具…

Linux学习笔记(Socket)

Linux-Socket 1、基础知识2、服务端3、客户端4、读写操作4.1、读写函数4.2、阻塞IO和非阻塞IO 5、例程 1、基础知识 socket用于计算机之间的网络通信&#xff0c;无论是构建服务器还是客户端&#xff0c;我们仅需要三个信息&#xff0c;服务器的ip地址&#xff0c;对应进程的端…

OpenAI 新发布的 GPT-4o,有血有肉的Ai来了,可实时语音视频交互

今天&#xff0c;OpenAI又又又开发布会了。 在大众心里&#xff0c;现在也基本上都知道&#xff0c;奥特曼是一个贼能PR的人。 每一次的PR的时间点&#xff0c;都拿捏的极其到位&#xff0c;精准的狙击其他厂商。比如说上一次Sora&#xff0c;其实你会发现从头到尾就是一个PR的…

奥维地图下载高清影像的两种方式!以及ArcGIS、QGIS、GlobalMapper、自编工具下载高清影像的方法推荐!

今天来介绍一下奥维互动地图是如何下载高清影像的&#xff0c;也不是多了不起的功能&#xff01;有朋友问&#xff0c;加上这个软件确实用的人多。 下载的高清数据在ArcGIS中打开的效果&#xff01; 开始介绍奥维之前我们也介绍一下我们之前介绍的几个方法&#xff0c;没有优劣…

zabbix触发器配置定期生效教程

在企业生产过程中&#xff0c;并非所有的设备都需要全天候、满负载运转&#xff0c;也有些仅需要周期性的运转即可。例如&#xff0c;在某家企业&#xff0c;有一批这样的机器&#xff0c;每天都会在固定的时间跑批量任务&#xff0c;期间&#xff0c;机器的CPU使用率会有明显的…

LeetCode 126题:单词接龙 II

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航&#xff1a; LeetCode解锁100…

联软安渡 UniNXG 安全数据交换系统 任意文件读取漏洞复现

0x01 产品简介 联软安渡UniNXG安全数据交换系统,是联软科技自研的业内融合网闸、网盘和DLP的一体机产品,它同时支持多网交换,查杀毒、审计审批、敏感内容识别等功能,是解决用户网络隔离、网间及网内数据传输、交换、共享/分享、存储的理想安全设备,具有开创性意义。 UniN…

什么是BI看板?选择BI看板制作工具时一定要考虑这些方面

BI看板也称为商业智能仪表板&#xff0c;是一种直观的数据可视化工具&#xff0c;它将关键业务指标&#xff08;KPIs&#xff09;和数据以图表、图形和表格的形式集中展示&#xff0c;使用户能够快速获取企业运营的实时概览。 这种数据可视化方式不仅使得复杂的数据信息易于理…

FPGA - Xilinx系列高速收发器---GTX

1&#xff0c;GTX是什么&#xff1f; GT &#xff1a;Gigabit Transceiver千兆比特收发器&#xff1b; GTX &#xff1a;Xilinx 7系列FPGA的高速串行收发器&#xff0c;硬核 xilinx的7系列FPGA根据不同的器件类型&#xff0c;集成了GTP、GTX、GTH、GTZ四种串行高速收发器&am…

(python)cryptography-安全的加密

前言 cryptography 是一个广泛使用的 Python 加密库&#xff0c;提供了各种加密、哈希和签名算法的实现。它支持多种加密算法&#xff0c;如 AES、RSA、ECC 等&#xff0c;以及哈希函数&#xff08;如 SHA-256、SHA-384 等&#xff09;和数字签名算法(如 DSA、ECDSA 等). 目录 …

pikachu靶场通关之csrf漏洞通关教程

目录 CSRF&#xff08;get型&#xff09; 1.打开网站&#xff0c;点击右上角提示 2.登录之后&#xff0c;点击修改个人信息 3.修改上述内容&#xff0c;打开抓包工具 4.抓到修改用户信息的数据包 5.构造虚假url&#xff0c;诱导用户点击 6.弹到修改后的界面 ​编辑 7.返…

前端已死? Bootstrap--CSS组件

目录 Bootstrap 下载 Bootstrap--全局CSS样式 栅格系统 栅格参数 正常显示 实例 代码演示: 排版 代码演示 表格 代码演示 表单 代码演示 等等...(文档很清晰了) Bootstrap--组件 结合演示:(页面) Bootstrap Bootstrap v3 中文文档 Bootstrap 是最受欢迎的 HT…