SpringBoot原理分析-1

SpringBoot原理分析

作为一个javaer,和boot打交道是很常见的吧。熟悉boot的人都会知道,启动一个springboot应用,就是用鼠标点一下启动main方法,然后等着就行了。我们来看看这个main里面。

@SpringBootApplication
public class ExampleApplication {public static void main(String[] args) {SpringApplication.run(ExampleApplication.class, args);}
}

这个类很简单吧,有三个注意点。

  • ExampleApplication就是类名,为了规范起见,这个类名一般都是xxxApplication。
  • 有一个注解@SpringBootApplication。
  • 然后就一个main方法,里面使用了SpringApplication的静态方法run(),传进去了俩参数。

这就神奇地启动起来了,为什么呢?

分析的版本:SpringBoot 2.7.18

需要结合以前用xml文件来配置Spring容器的形式来对比Boot用注解的形式

1.注解&自动配置

目前只知道注解的作用即可,至于这些注解是怎么起作用的,见后续...

@SpringBootApplication

这一节来详细聊一聊这个注解。@SpringBootApplication 是 Spring Boot 框架中的一个核心注解,用于简化 Spring Boot 应用的配置和启动

它的作用

  • @SpringBootApplication 标注在应用的主类上,用于启动 Spring Boot 应用。
  • 它启用了 Spring Boot 的自动配置机制,根据项目的依赖自动配置 Spring 应用。
  • 组件扫描:它启用了组件扫描,自动发现并注册带有 @Component@Service@Repository@Controller 等注解的类。
  • 配置类:它标记该类为 Spring 的配置类,相当于 @Configuration 注解。

点进去看看,该注解的结构如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited // 四个元注解
@SpringBootConfiguration
@EnableAutoConfiguration //启用SpringBoot的自动配置机制。SpringBoot会根据类路径中的依赖自动配置应用。例如,如果类路径中有spring-boot-starter-web,SpringBoot会自动配置Tomcat和SpringMVC。@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) // 启用组件扫描,并排除一些特定的过滤器。默认是注解标注的类所在包及其子包。实际上是不是就是主启动类所在包及其子包!!!!!
public @interface SpringBootApplication {
..............
}// 发现这是一个组合注解

@SpringBootConfiguration 注解:主要作用是标记一个类为 Spring Boot 的配置类与 @Configuration 类似,但它专门用于 Spring Boot 应用。这个注解和@ComponentScan注解结合到一起,达成了如下效果。(左边是xml文件配置形式,右边是SpringBoot注解的形式),这俩注解在一起,就是扫描主启动类所在包及其子包下的被@Controller、@Service、.....标注的类,将他们归到Spring容器里面去。

@EnableAutoConfiguration

@EnableAutoConfiguration注解: 这个注解不得了啊。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class) // 这里。
public @interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";Class<?>[] exclude() default {};String[] excludeName() default {};}

发现@Import注解。这个注解的作用是干啥的?这里给出GPT的回答:@Import 是 Spring 框架提供的一个注解,用于将一个或多个配置类(@Configuration 类)组件类导入到当前的 Spring 应用上下文中。它可以用来显式地引入其他配置类或 Bean 定义,从而实现模块化配置和代码复用。

这里有一个非常重要的东西,那就是当前的Spring上下文,也就是主启动类所在包及其子包,@Import(AutoConfigurationImportSelector.class)这句话的意思是将SpringBoot官方写的AutoConfigurationImportSelector类导入到当前Spring上下文中,在当前Spring上下文注册这样一个bean。

AutoConfigurationImportSelector探究

public interface ImportSelector {String[] selectImports(AnnotationMetadata importingClassMetadata);
}
// 实现了DeferredImportSelector接口,DeferredImportSelector实现了ImportSelector
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {...........AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata); // 1.进去return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}// 2.这个方法protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;}AnnotationAttributes attributes = getAttributes(annotationMetadata);// 3.进入这里List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);...........}// 4. 3调用的这个方法protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {List<String> configurations = new ArrayList<>(// 5. 继续往下SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);Assert.notEmpty(configurations,"No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "+ "are using a custom packaging, make sure that file is correct.");return configurations;}// 6. 5处调用的方法public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {...... // loadSpringFactoriesreturn loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());}// 7// 最终可以在loadSpringFactories方法里面看到这样一行代码//Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);// public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";// 结合官方给的解释The location to look for factories. Can be present in multiple JAR files. 寻找工厂的位置。可以存在于多个 JAR 文件中。
}

结合idea打断点调试:我们发现getCandidateConfigurations扫描到了引入的所有jar包的META-INF/spring.factories,共有156个xxxAutoConfigure类。但是这些都会用到吗,别忘了,SpringBoot有个非常强大的特点:那就是导入场景、对应的场景才会生效!!

继续往下走,请看下图:(发现只有50个了,例如上图里面的amqp,由于项目中没有用到,故在这里就没有了,经过了filter过滤)

以RabbitMq自动配置为例

@AutoConfiguration
@ConditionalOnClass({ RabbitTemplate.class, Channel.class }) // 这两个类存在时才生效,项目里面没导入相关jar包,故RabbitAutoConfiguration不会被导入Spring容器生效,下面就来说这个注解
@EnableConfigurationProperties(RabbitProperties.class)
@Import({ RabbitAnnotationDrivenConfiguration.class, RabbitStreamConfiguration.class })
public class RabbitAutoConfiguration {................
}

@ConditionalOnClass

先看看其源码

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class) // 这里***
public @interface ConditionalOnClass {Class<?>[] value() default {};String[] name() default {};
}

@ConditionalOnClass注解的作用是当项目中存在某个类时才会使标有该注解的类或方法生效;

先看我们的主类【1. 此时,没有引入test.demo.test.list.Student所在的maven依赖】

/* 下面是这俩类
public class Cat {private Integer id;private String name;
}
public class Dog {private Integer id;private String name;
}*/@SpringBootApplication
@MapperScan("com.feng.tackle.dao")
public class DateApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(DateApplication.class, args);ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();Iterator<String> iterator = beanFactory.getBeanNamesIterator();while (iterator.hasNext()) {String name = iterator.next();if ( name.equals("dog01") || name.equals("cat01") ) System.out.println(name); // 看看有没有这两个名字的bean}}
}
// 最后的输出结果
/*
cat01
*/

在配置类中,我们这样做

@Configuration
public class ConditionTestConfig {@ConditionalOnClass(name = "test.demo.test.list.Student") // 类路径有这个类,就往容器中放入该bean@Beanpublic Dog dog01() {return new Dog(2, "汪汪汪");}@ConditionalOnMissingClass("test.demo.test.list.Student") // 类路径没有这个类,就往容器中放入该bean@Beanpublic Cat cat01() {return new Cat(1, "喵喵喵");}
}

main最后的输出结果是cat01。"test.demo.test.list.Student"是另一个maven项目里面的类。

【2. 项目中引入Student所在的maven】

<dependency><groupId>com.feng.test</groupId><artifactId>test-demo</artifactId><version>1.0-SNAPSHOT</version>
</dependency>

再次启动main,输出结果dog01

通过这个例子,我们可以知道SpringBoot自动配置,导入具体starter,对应的场景才会生效。【由于没有导入MQ的starter,故此配置类不会生效】

总结

**自动配置: **

以spring-boot-starter-web为例子,引入该启动器,他的父级pom里面有spring-boot-starter,spring-boot-starter的父级pom有spring-boot-autoconfigure。

spring-boot-autoconfigure里面有Spring官方定义的所有场景。

  • @EnableAutoConfiguration 注解:这是自动配置的入口,通常由 @SpringBootApplication 注解组合引入。
  • spring.factories 文件:Spring Boot 通过 META-INF/spring.factories 文件加载自动配置类。
  • 条件化配置:通过 @Conditional 系列注解(如 @ConditionalOnClass@ConditionalOnMissingBean 等)实现按需加载配置。

自动配置的流程:

  1. 加载自动配置类
  • @SpringBootApplication 注解:该注解是一个组合注解,包含了 @EnableAutoConfiguration,用于启用自动配置。
  • @EnableAutoConfiguration 的作用:该注解会通过 SpringFactoriesLoader 加载 META-INF/spring.factories 文件中定义的自动配置类。
  1. 条件化配置

自动配置类通常使用 @Conditional 系列注解来控制是否生效

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class })
public class DataSourceAutoConfiguration {// 自动配置逻辑
}
//如果类路径中存在 DataSource 和 EmbeddedDatabaseType,且容器中没有 ConnectionFactory Bean,则自动配置 DataSource。
  1. 加载配置属性
  • @EnableConfigurationProperties:自动配置类通常会通过该注解加载配置属性。
  • application.propertiesapplication.yml:Spring Boot 会读取这些配置文件中的属性,并将其绑定到对应的配置类中。
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties {private String url;private String username;private String password;// getters and setters
}
  1. 注册bean
  • 自动配置类通过 @Bean 方法向容器中注册 Bean。
  • 这些 Bean 通常是框架的核心组件,如 DataSourceDispatcherServletSecurityFilterChain 等。

2. 启动过程

SpringApplication.run(ExampleApplication.class, args);这一行代码做了啥?这才是重点!

从run开始看,一层一层往下面点进去

// 1.
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) { // 会返回一个正在运行的Spring容器return run(new Class<?>[] { primarySource }, args); // 调用重载的run方法
}
// 2.
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {return new SpringApplication(primarySources).run(args); // 先调用该构造方法,然后再调用run方法,将程序参数传进去
}
// 3.
public SpringApplication(Class<?>... primarySources) {this(null, primarySources); //primarySource 是传入的主配置类(通常带有 @SpringBootApplication 注解的类),Spring Boot 会将其作为配置源。
}// 4. [构造方法] 构造方法
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {........ // 见下一节构造方法
}

先调用该构造方法,然后再调用run方法

①构造方法

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {this.resourceLoader = resourceLoader; // null的Assert.notNull(primarySources, "PrimarySources must not be null");this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));  // 一、设置主配置类this.webApplicationType = WebApplicationType.deduceFromClasspath();  // 二、推断应用类型this.bootstrapRegistryInitializers = new ArrayList<>( // 三、getSpringFactoriesInstances(BootstrapRegistryInitializer.class));setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));// 四、setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));// 五、this.mainApplicationClass = deduceMainApplicationClass(); // 六、通过堆栈信息推断出主类(即 main 方法所在的类)。
}

1.推断应用类型

  • WebApplicationType.deduceFromClasspath() 方法会根据类路径中是否存在特定的类来推断应用类型。
  • 可能的类型包括:
    • WebApplicationType.SERVLET:基于 Servlet 的 Web 应用(如 Spring MVC)。
    • WebApplicationType.REACTIVE:基于 Reactive 的 Web 应用(如 Spring WebFlux)。
    • WebApplicationType.NONE:非 Web 应用。

2.加载并初始化 BootstrapRegistryInitializer 实例

分析一下核心方法getSpringFactoriesInstances,下面两个都会调用这个。

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {ClassLoader classLoader = getClassLoader();// Use names and ensure unique to protect against duplicatesSet<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); // 下一步List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);AnnotationAwareOrderComparator.sort(instances);return instances;
}// SpringFactoriesLoader.loadFactoryNames(type, classLoader) 到这儿来了
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {ClassLoader classLoaderToUse = classLoader;if (classLoaderToUse == null) {classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();}String factoryTypeName = factoryType.getName();return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}//loadSpringFactories(classLoaderToUse)
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {// static final Map<ClassLoader, Map<String, List<String>>> cache = new ConcurrentReferenceHashMap<>();// 从缓存map中拿到对应classLoader的map,如果该classLoader已经存在了,就不用走下面的了Map<String, List<String>> result = cache.get(classLoader);if (result != null) {return result;}result = new HashMap<>();try {/*public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";结合官方给的解释The location to look for factories. Can be present in multiple JAR files. 寻找工厂的位置。可以存在于多个 JAR 文件中。*/Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);..............return result;
}

可以看到这里,在第一章《注解&自动配置》也出现了这个,如今在SpringApplication的构造方法,底层也调用到了这里。二者有什么区别或者联系呢?

SpringFactoriesLoader.loadFactoryNames是Spring Boot 提供的工具方法,用于从 META-INF/spring.factories 文件中加载指定类型的配置类。

两者都依赖于 META-INF/spring.factories 文件,该文件是 Spring Boot 自动配置和扩展机制的核心配置文件。两者都通过类路径扫描,加载所有 META-INF/spring.factories 文件,并解析出指定类型的配置类。

(1)调用位置

  • AutoConfigurationImportSelector
    • 位于 org.springframework.boot.autoconfigure 包中。
    • 是 Spring Boot 自动配置的核心组件之一,负责加载自动配置类。
    • 在 Spring 容器的配置类解析阶段被调用(具体是在 @EnableAutoConfiguration 注解的处理过程中)。
  • SpringApplication
    • 位于 org.springframework.boot 包中。
    • 是 Spring Boot 应用的启动类,负责初始化应用上下文、加载配置等。
    • 在应用启动时被调用。

(2)加载的配置类型

  • AutoConfigurationImportSelector
    • 主要加载 META-INF/spring.factories 文件中 org.springframework.boot.autoconfigure.EnableAutoConfiguration 键下的自动配置类。
    • 这些配置类用于实现 Spring Boot 的自动配置功能(如 DataSourceAutoConfigurationWebMvcAutoConfiguration 等)。
  • SpringApplication
    • 加载多种类型的配置类,包括:
      • ApplicationContextInitializer
      • ApplicationListener
      • BootstrapRegistryInitializer
    • 这些配置类用于初始化应用上下文、监听应用事件等。

(3)调用时机

  • AutoConfigurationImportSelector
    • 在 Spring 容器解析配置类时调用(具体是在 ConfigurationClassPostProcessor 处理 @Configuration 类时)。
    • 属于 Spring 容器初始化的早期阶段。
  • SpringApplication
    • 在应用启动时调用(具体是在 SpringApplication 的构造方法或 run 方法中)。
    • 属于应用启动的早期阶段。

(4)返回值的使用

  • AutoConfigurationImportSelector
    • 返回的自动配置类会被 Spring 容器加载并处理,最终生成相应的 Bean 定义。
    • 这些配置类通常包含 @Configuration 注解和 @Conditional 注解,用于按需加载 Bean。
  • SpringApplication
    • 返回的配置类会被直接实例化并注册到应用中。
    • 例如,ApplicationContextInitializer 会被调用以初始化应用上下文,ApplicationListener 会被注册以监听应用事件。

3.加载并设置 ApplicationContextInitializer 实例

同2

4.加载并设置 ApplicationListener 实例

同2

总结

  • BootstrapRegistryInitializer:用于应用启动的最早阶段,初始化引导阶段的组件。
  • ApplicationContextInitializer:用于在 ApplicationContext 创建之后、刷新之前,对上下文进行自定义初始化。
  • ApplicationListener:用于监听应用生命周期中的事件,并在特定阶段执行逻辑。

这三者共同扩展了 Spring Boot 应用的启动过程,提供了灵活的扩展点,可以满足不同场景下的需求。

5.三者的实现

分别编写实现类

public class MyBootstrapInit implements BootstrapRegistryInitializer {@Overridepublic void initialize(BootstrapRegistry registry) {System.out.println("【MyBootstrapInit】--------------方法执行了");}
}public class MyApplicationContextInit implements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {System.out.println("【MyApplicationContextInit】------------" + applicationContext.getApplicationName());}
}public class MyContextListener implements ApplicationListener<ApplicationStartedEvent> { // 该监听器对此事件感兴趣@Overridepublic void onApplicationEvent(ApplicationStartedEvent event) {System.out.println("【MyContextListener】--监听器--" + event.getSource());}
}

然后在resource目录下面创建META-INF,在其中的spring.factories中

org.springframework.boot.BootstrapRegistryInitializer=com.feng.tackle.config.source.MyBootstrapInit
org.springframework.context.ApplicationContextInitializer=com.feng.tackle.config.source.MyApplicationContextInit
org.springframework.context.ApplicationListener=com.feng.tackle.config.source.MyContextListener

启动应用:

疑问? 我可以在这三者的实现类上面加@Configuration注解,不要spring.factories,可以实现类似效果吗?

答案是,只有ApplicationListener可以。为什么?请看下面的run方法里面

②run

public ConfigurableApplicationContext run(String... args) {// 记录应用启动的开始时间,用于后续计算启动耗时。long startTime = System.nanoTime(); //创建一个 BootstrapContext,用于在应用启动的早期阶段提供一些基础设施支持(如环境配置、属性源等)================DefaultBootstrapContext bootstrapContext = createBootstrapContext();ConfigurableApplicationContext context = null;// 设置系统属性 java.awt.headless,确保应用在没有图形界面环境(如服务器)中也能正常运行configureHeadlessProperty();/*获取所有 SpringApplicationRunListener 实例,用于监听应用启动的各个阶段。调用 listeners.starting(),通知监听器应用正在启动。*/SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting(bootstrapContext, this.mainApplicationClass);try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 加载和配置应用的环境(Environment),包括配置文件(如 application.properties 或 application.yml)、命令行参数等。ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);configureIgnoreBeanInfo(environment);// 打印 Spring Boot 的启动 Banner(默认或自定义)。Banner printedBanner = printBanner(environment);// 根据应用类型(Servlet、Reactive 等)创建相应的 ApplicationContext。context = createApplicationContext();context.setApplicationStartup(this.applicationStartup);// 准备应用上下文prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);// 调用 AbstractApplicationContext.refresh() 方法,完成 Bean 的实例化、依赖注入和初始化。refreshContext(context);afterRefresh(context, applicationArguments);// 计算启动耗时并记录日志。Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);}listeners.started(context, timeTakenToStartup);// 执行所有 ApplicationRunner 和 CommandLineRunner 的实现类,用于在应用启动后执行自定义逻辑。callRunners(context, applicationArguments);}catch (Throwable ex) {handleRunFailure(context, ex, listeners);throw new IllegalStateException(ex);}try {// 计算应用启动到就绪的总耗时。Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);listeners.ready(context, timeTakenToReady);}catch (Throwable ex) {handleRunFailure(context, ex, null);throw new IllegalStateException(ex);}return context;
}

这个run这里分析得不够深入。受篇幅影响,在后续文章中再来分析。

end. 参考

  1. 尚硅谷雷丰阳老师的课

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

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

相关文章

CF补题 950-Div.3

CF补题 950-Div.3-20250102 Dashboard - Codeforces Round 950 (Div. 3) - Codeforces A: 题目大意:给出一个字符串,要求重复的字母必须 \(\ge m\) ,求缺失字母总个数 #include <iostream> #include <map> using namespace std;map<char, int> mp;int ma…

第十五周学习总结

学期2024-2025-1 学号20241414 《计算机基础与程序设计》第十五周学习总结 作业信息这个作业属于哪个课程 2024-2025-1-计算机基础与程序设计这个作业要求在哪里 2024-2025-1计算机基础与程序设计第一周作业这个作业的目标 课程总结作业正文 本博客链接每周作业链接汇总整体评价…

【ADB基础】ADB及Monkey测试

什么是monkey Monkey 是Android SDK提供的一个命令行工具,可以简单方便的发送伪随机的用户事件流,对Android APP做压力(稳定性)测试。主要是为了测试app是否存在无响应和崩溃的情况。 monkey命令说明monkey 测试命令使用及详细说明 常用命令 语法:adb shell monkey -p 包名…

20241314 《计算机基础与程序设计》课程总结

20241314 《计算机基础与程序设计》课程总结每周作业链接汇总第一周课程概论 工业革命与浪潮之巅 信息与信息安全 计算机系统概论 计算机安全 计算的限制思维作业第二周课程概论 数字化与信息安全第三周课程概论 数字逻辑门 数据类型 冯诺依曼体系第四周课程概论 计算机系统 计…

同硕计算机专业:统考+课程+源码学习资料全部免费送!

考研之路,道阻且长。对于计算机专业的学子来说,备考之路更是充满挑战。为了帮助广大考生高效备战,我在此精心整理了一套同硕计算机专业统考历年真题和复习重点、专业课程学习和相关源码资料,并免费分享给大家!我的全部学习资料都放在那里,后续我还会增加资料分享放在那里…

20241316 《计算机基础与程序设计》课程总结

20241316 《计算机基础与程序设计》课程总结第一周作业:浏览教材并提出问题第二周作业: 自学教材计算机科学概论(第七版)第1章并完成云班课测试 《C语言程序设计》第1章并完成云班课测试第三周作业:计算机科学概论(第七版)第2章,第3章 并完成云班课测试第四周作业:学习…

Windows环境下反弹shell各类姿势

在渗透测试过程中我们有时候需要通过Windows平台来反弹shell到我们的VPS主机以及CS端,那么这个过程中我们就需要借助Windows平台内置的可执行程序来执行命令,其中首选的就是powershell,本篇文章我们主要介绍如何通过Windows平台中如何通过powershell来反弹shell操作。 power…

集成运算放大器的简单介绍

集成运算放大器是一种具有很高放大倍数的多级直接耦合放大电路。是发展最早、应用最广泛的一种模拟电路。 集成电路是把整个电路的各个元件以及相互之间的连接同时制造在一块半导体芯片上,组成一个不可分点整体。 集成电路的特点:体积小,重量轻、功耗低、可靠性高、成本低、…

利用huggingface尝试的第一个简单的文本分类任务

` 这是一个简单的文本分类任务,基本的流程步骤还是挺清晰完整的,和之前那个简单的cnn差不多, 用到了transformers包,还需用到huggingface的模型rbt3, 但是好像连接不上``遇到的问题: 1.导入的包不可用,从AutoModelForTokenClassification换成了AutoModelForSequenceC…

【嵌入式编程】内存分布

一、内存分布图在操作系统中,内存被组织和管理以支持进程的运行。以下是一些常见的内存分布概念: 【内核空间】:操作系统内核使用的内存区域,用于存储内核代码、数据结构和进程控制块(PCB)。【用户空间】:存储用户的代码。未初始化变量区(.bss):存放未初始化的全局变量…

北京健康证(立水桥地铁站附近)

体检:记得带身份证就可以,最好自带一支笔,用他的笔要排队,我买的是96的,带培训证的。 下面这个表只填:身份证号,手机号,姓名就可以,类别、是否培训以交钱时候前台登记的为准,照片也不采集,直接用身份证上的相片

北京健康证

体检:记得带身份证就可以,我买的是96的,带培训证的。 下面这个表只填:身份证号,手机号,姓名就可以,类别以交钱时候前台登记的为准,照片也不采集,直接用身份证上的相片