分析 SpringBoot 底层机制【Tomcat 启动分析 +Spring 容器初始化 +Tomcat 如何关联 Spring 容器 】

news2025/1/13 9:36:53

目录

一.搭建 SpringBoot 底层机制开发环境

1.pom.xml文件配置

2.springboot主程序MainApp.java

3.启动项目,然后我们准备开始思考

4.开始思考

底层机制分析: 仍然是 我们实现 Spring 容器那一套机制 IO/文件扫描+注解+反射+ 集合+映射集合+映射

二.源码分析: SpringApplication.run()

重点

三.实现 SpringBoot 底层机制 【Tomcat 启动分析 + Spring 容器初始化+Tomcat 如何关联Spring 容器 】

1.实现任务阶段 1- 创建 Tomcat, 并启动

1.1说明: 创建 Tomcat, 并启动

1.2分析+代码实现

2.实现任务阶段 2- 创建 Spring 容器

2.1说明: 创建 Spring 容器

2.2 分析+代码实现

3.实现任务阶段 3- 将 Tomcat 和 Spring 容器关联, 并启动 Spring 容器

3.1 说明: 将 Tomcat 和 Spring 容器关联, 并启动 Spring 容器

3.2 分析+代码实现

3.3debug 一下, 看看是否进行 Spring 容器的初始化工作, 可以看到 ac.refresh() 会将


一.搭建 SpringBoot 底层机制开发环境

1.pom.xml文件配置

    <!-- 导入 springboot 父工程,规定的写法 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.3</version>
    </parent>
    <!-- 导入 web 项目场景启动器,会自动导入和 web 开发相关依赖,非常方便 -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
     <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jasper</artifactId>
            <version>8.5.75</version>
        </dependency>
    </dependencies>

2.springboot主程序MainApp.java

@SpringBootApplication
public class MainApp {
    public static void main(String[] args) {
        ConfigurableApplicationContext ioc =
             SpringApplication.run(Main.class, args);

    }

3.启动项目,然后我们准备开始思考

我们发现当我们启动项目的时候tomcat也会直接启动,底层到底发生了什么? 

4.开始思考

首先先建立一个Dog的文件

之后我们将这个文件config写出来

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 海绵hong
 * @Date: 2022/11/19/22:55
 * @Description:标识标识的是一个配置类,充当Spring配置文件/容器的角色
 * 如果该配置类,如果在springboot扫描的包/子包,会被注入到容器中
 * 在该类中,可以通过这个注解@Bean来注入其他的主键
 */
@Configuration
public class Config {

    /**
     * 1. 通过@Bean的方式, 将new出来的Bean对象, 放入到Spring容器
     * 2. 该bean在Spring容器的name/id 默认就是 方法名
     * 3. 通过方法名, 可以得到注入到spring容器中的dog对象
     **/
    @Bean
    public Dog dog(){
        return new Dog();
    }

}

底层机制分析: 仍然是 我们实现 Spring 容器那一套机制 IO/文件扫描+注解+反射+ 集合+映射集合+映射

二.源码分析: SpringApplication.run()

1 Debug SpringApplication . run ( MainApp . class , args) 看看 SpringBoot 是如何启动 Tomcat .
2 、我们的 Debug 目标 : 紧抓一条线 , 就是看到 tomcat 被启动的代码 . 比如 tomcat.start()
package com.hong.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * @author 韩顺平
 * @version 1.0
 */
@SpringBootApplication
public class MainApp {
    public static void main(String[] args) {

        //启动springboot应用程序/项目
        //提出问题: 当我们执行run方法时,怎么就启动我们的内置的tomcat?
        //在分析run方法的底层机制的基础上,我们自己尝试实现
        ConfigurableApplicationContext ioc =
                SpringApplication.run(MainApp.class, args);

        /**
         *  这里我们开始Debug SpringApplication.run()
         *  1. SpringApplication.java
         *  public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
         * 		return run(new Class<?>[] { primarySource }, args);
         *   }
         *
         *  2.SpringApplication.java : 创建返回 ConfigurableApplicationContext对象
         *  public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
         * 		return new SpringApplication(primarySources).run(args);
         *        }
         *
         *  3. SpringApplication.java
         *
         *  public ConfigurableApplicationContext run(String... args) {
         * 		StopWatch stopWatch = new StopWatch();
         * 		stopWatch.start();
         * 		DefaultBootstrapContext bootstrapContext = createBootstrapContext();
         * 		ConfigurableApplicationContext context = null;
         * 		configureHeadlessProperty();
         * 		SpringApplicationRunListeners listeners = getRunListeners(args);
         * 		listeners.starting(bootstrapContext, this.mainApplicationClass);
         * 		try {
         * 			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
         * 			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
         * 			configureIgnoreBeanInfo(environment);
         * 			Banner printedBanner = printBanner(environment);
         * 			context = createApplicationContext(); //严重分析: 创建容器
         * 			context.setApplicationStartup(this.applicationStartup);
         * 			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
         * 			refreshContext(context); //严重分析: 刷新应用程序上下文,比如 初始化默认设置/注入相关Bean/启动tomcat
         * 			afterRefresh(context, applicationArguments);
         * 			stopWatch.stop();
         * 			if (this.logStartupInfo) {
         * 				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
         *                        }
         * 			listeners.started(context);
         * 			callRunners(context, applicationArguments);* 		}
         * 		catch (Throwable ex) {
         * 			handleRunFailure(context, ex, listeners);
         * 			throw new IllegalStateException(ex);
         * 		}
         *
         * 		try {
         * 			listeners.running(context);
         * 		}
         * 		catch (Throwable ex) {
         * 			handleRunFailure(context, ex, null);
         * 			throw new IllegalStateException(ex);
         * 		}
         * 		return context;
         * 	}
         *
         * 	4. SpringApplication.java : 容器类型很多,会根据你的this.webApplicationType创建对应的容器
         * 	默认 this.webApplicationType 是 SERVLET 也就是web容器/可以处理servlet
         * 	protected ConfigurableApplicationContext createApplicationContext() {
         * 		return this.applicationContextFactory.create(this.webApplicationType);
         *        }
         *
         *  5. ApplicationContextFactory.java
         *
         *  ApplicationContextFactory DEFAULT = (webApplicationType) -> {
         * 		try {
         * 			switch (webApplicationType) {
         * 			case SERVLET://默认是进入到这个分支 ,返回AnnotationConfigServletWebServerApplicationContext容器
         * 				return new AnnotationConfigServletWebServerApplicationContext();
         * 			case REACTIVE:
         * 				return new AnnotationConfigReactiveWebServerApplicationContext();
         * 			default:
         * 				return new AnnotationConfigApplicationContext();
         *                        }* 		}
         * 		catch (Exception ex) {
         * 			throw new IllegalStateException("Unable create a default ApplicationContext instance, "
         * 					+ "you may need a custom ApplicationContextFactory", ex);
         * 		}
         * 	};
         *
         * 	6. SpringApplication.java
         * 	private void refreshContext(ConfigurableApplicationContext context) {
         * 		if (this.registerShutdownHook) {
         * 			shutdownHook.registerApplicationContext(context);
         *                }
         * 		refresh(context); //严重分析,真正执行相关任务
         *  }
         *
         *  7. SpringApplication.java
         *  protected void refresh(ConfigurableApplicationContext applicationContext) {
         * 		applicationContext.refresh();
         *    }
         *
         *
         *  8. ServletWebServerApplicationContext.java
         *  @Override
         *        public final void refresh() throws BeansException, IllegalStateException {
         * 		try {
         * 			super.refresh();//分析这个方法
         *        }
         * 		catch (RuntimeException ex) {
         * 			WebServer webServer = this.webServer;
         * 			if (webServer != null) {
         * 				webServer.stop();
         *            }
         * 			throw ex;
         *        }
         *    }
         *
         * 9. AbstractApplicationContext.java
         *
         * @Override
         *        public void refresh() throws BeansException, IllegalStateException {
         * 		synchronized (this.startupShutdownMonitor) {
         * 			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
         *
         * 			// Prepare this context for refreshing.
         * 			prepareRefresh();
         *
         * 			// Tell the subclass to refresh the internal bean factory.
         * 			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
         *
         * 			// Prepare the bean factory for use in this context.
         * 			prepareBeanFactory(beanFactory);
         *
         * 			try {
         * 				// Allows post-processing of the bean factory in context subclasses.
         * 				postProcessBeanFactory(beanFactory);
         *
         * 				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
         * 				// Invoke factory processors registered as beans in the context.
         * 				invokeBeanFactoryPostProcessors(beanFactory);
         *
         * 				// Register bean processors that intercept bean creation.
         * 				registerBeanPostProcessors(beanFactory);
         * 				beanPostProcess.end();
         *
         * 				// Initialize message source for this context.
         * 				initMessageSource();
         *
         * 				// Initialize event multicaster for this context.
         * 				initApplicationEventMulticaster();
         *
         * 				// Initialize other special beans in specific context subclasses.
         * 				onRefresh(); //严重分析,当父类完成通用的工作后,再重新动态绑定机制回到子类
         *
         * 				// Check for listener beans and register them.
         * 				registerListeners();
         *
         * 				// Instantiate all remaining (non-lazy-init) singletons.
         * 				finishBeanFactoryInitialization(beanFactory);
         *
         * 				// Last step: publish corresponding event.
         * 				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...
         * 				resetCommonCaches();
         * 				contextRefresh.end();
         *            }
         *        }
         *    }
         *  10. ServletWebServerApplicationContext.java
         *  @Override
         * 	protected void onRefresh() {
         * 		super.onRefresh();
         * 		try {
         * 			createWebServer();//看到胜利的曙光,创建webserver 可以理解成会创建指定web服务-Tomcat
         *                }
         * 		catch (Throwable ex) {
         * 			throw new ApplicationContextException("Unable to start web server", ex);
         *        }    * 	}
         *   11. ServletWebServerApplicationContext.java
         *
         *   private void createWebServer() {
         * 		WebServer webServer = this.webServer;
         * 		ServletContext servletContext = getServletContext();
         * 		if (webServer == null && servletContext == null) {
         * 			StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");
         * 			ServletWebServerFactory factory = getWebServerFactory();
         * 			createWebServer.tag("factory", factory.getClass().toString());
         * 			this.webServer = factory.getWebServer(getSelfInitializer());//严重分析,使用TomcatServletWebServerFactory 创建一个TomcatWebServer
         * 			createWebServer.end();
         * 			getBeanFactory().registerSingleton("webServerGracefulShutdown",
         * 					new WebServerGracefulShutdownLifecycle(this.webServer));
         * 			getBeanFactory().registerSingleton("webServerStartStop",
         * 					new WebServerStartStopLifecycle(this, this.webServer));
         *                }
         * 		else if (servletContext != null) {
         * 			try {
         * 				getSelfInitializer().onStartup(servletContext);
         *            }
         * 			catch (ServletException ex) {
         * 				throw new ApplicationContextException("Cannot initialize servlet context", ex);
         *            }
         *        }
         * 		initPropertySources();    * 	}
         *
         * 	12. TomcatServletWebServerFactory.java 会创建Tomcat 并启动Tomcat
         *
         *        @Override
         *    public WebServer getWebServer(ServletContextInitializer... initializers) {
         * 		if (this.disableMBeanRegistry) {
         * 			Registry.disableRegistry();
         *        }
         * 		Tomcat tomcat = new Tomcat();//创建了Tomcat对象
         * 		File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
         * 	    //做了一系列的设置
         * 		tomcat.setBaseDir(baseDir.getAbsolutePath());
         *
         * 		Connector connector = new Connector(this.protocol);
         * 		connector.setThrowOnFailure(true);
         * 		tomcat.getService().addConnector(connector);
         * 		customizeConnector(connector);
         * 		tomcat.setConnector(connector);
         * 		tomcat.getHost().setAutoDeploy(false);
         * 		configureEngine(tomcat.getEngine());
         * 		for (Connector additionalConnector : this.additionalTomcatConnectors) {
         * 			tomcat.getService().addConnector(additionalConnector);
         *        }
         * 		prepareContext(tomcat.getHost(), initializers);
         * 		return getTomcatWebServer(tomcat); //严重分析该方法.
         *    }
         *
         *    13. TomcatServletWebServerFactory.java , 这里做了校验创建 TomcatWebServer
         *    protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
         * 		return new TomcatWebServer(tomcat, getPort() >= 0, getShutdown());
         *        }
         *    14. TomcatServletWebServerFactory.java
         *    public TomcatWebServer(Tomcat tomcat, boolean autoStart, Shutdown shutdown) {
         * 		Assert.notNull(tomcat, "Tomcat Server must not be null");
         * 		this.tomcat = tomcat;
         * 		this.autoStart = autoStart;
         * 		this.gracefulShutdown = (shutdown == Shutdown.GRACEFUL) ? new GracefulShutdown(tomcat) : null;
         * 		initialize();//分析这个方法.
         *        }
         *    15.TomcatServletWebServerFactory.java
         *
         *    private void initialize() throws WebServerException {
         * 		logger.info("Tomcat initialized with port(s): " + getPortsDescription(false));
         * 		synchronized (this.monitor) {
         * 			try {
         * 				addInstanceIdToEngineName();
         *
         * 				Context context = findContext();
         * 				context.addLifecycleListener((event) -> {
         * 					if (context.equals(event.getSource()) && Lifecycle.START_EVENT.equals(event.getType())) {
         * 						// Remove service connectors so that protocol binding doesn't
         * 						// happen when the service is started.
         * 						removeServiceConnectors();
         *                                        }                * 				});
         *
         * 				// Start the server to trigger initialization listeners
         * 				this.tomcat.start(); //启动Tomcat
         *
         * 				// We can re-throw failure exception directly in the main thread
         * 				rethrowDeferredStartupExceptions();
         *
         * 				try {
         * 					ContextBindings.bindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());
         *                }
         * 				catch (NamingException ex) {
         * 					// Naming is not enabled. Continue
         *                }
         *
         * 				// Unlike Jetty, all Tomcat threads are daemon threads. We create a
         * 				// blocking non-daemon to stop immediate shutdown
         * 				startDaemonAwaitThread();
         *            }
         * 			catch (Exception ex) {
         * 				stopSilently();
         * 				destroySilently();
         * 				throw new WebServerException("Unable to start embedded Tomcat", ex);
         *            }
         *        }
         *    }
         */
        System.out.println("hello ioc");

    }
}

重点

就是创建了一个容器,注入了相应的bean,启动了tomcat

三.实现 SpringBoot 底层机制 【Tomcat 启动分析 + Spring 容器初始化+Tomcat 如何关联Spring 容器 】

1.实现任务阶段 1- 创建 Tomcat, 并启动

1.1说明: 创建 Tomcat, 并启动

1.2分析+代码实现

● 代码实现        

1.修改pom.xml

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!--因为我们自己要创建Tomcat对象,并启动,
            因此我们先排除 内嵌的 spring-boot-starter-tomcat-->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!--我们指定tomcat版本,引入tomcat依赖/库

        1. 使用指定的tomcat 8.5.75
        2. 如果我们引入自己指定的tomcat,一定要记住把前面spring-boot-starter-tomcat排除
        3. 如果你不排除,会出现 GenericServlet Not Found错误提示
        -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>8.5.75</version>
        </dependency>



    </dependencies>

2.SpringApplication.java

public class HongSpringApplication {
    //这里我们会创建tomcat对象,并关联Spring容器, 并启动
    public static void run() {
        try {
            //创建Tomcat对象 HspTomcat
            Tomcat tomcat = new Tomcat();

            //设置9090
            tomcat.setPort(9090);
            //启动
            tomcat.start();
            //等待请求接入
            System.out.println("======9090====等待请求=====");
            tomcat.getServer().await();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

3.MainApp.java

public class HongMainApp {
    public static void main(String[] args) {
        //启动HspSpringBoot项目/程序
        HspSpringApplication.run();
    }
}

 

2.实现任务阶段 2- 创建 Spring 容器

2.1说明: 创建 Spring 容器

2.2 分析+代码实现

代码实现

1.Monster.java , 做一个测试 Bean

public class Monster {
}

2.HiController.java, 作为 Controller

@RestController
public class HiController {

    @RequestMapping("/hi")
    public String hi() {
        return "hi,hong HiController";
    }
}

3.HongConfig.java , 作为 Spring 的配置文件.

/**
 * @author 海绵hong
 * @version 1.0
 * HspConfig:配置类-作为Spring的配置文件
 * 这里有一个问题,容器怎么知道要扫描哪些包? =>一会代码会体现
 *
 * 在配置类可以指定要扫描包: @ComponentScan("com.hong.hongspringboot")
 */
@Configuration
@ComponentScan("com.hong.hongspringboot")
public class HongConfig {

    //注入Bean - monster 对象到Spring容器.
    @Bean
    public Monster monster() {
        return new Monster();
    }
}

4.WebApplicationInitializer.java , 作为 Spring 的容器.

/**
 * @author 海绵hong
 * @version 1.0
 * Initializer: 初始化器
 */

/**
 * 解读
 * 1. 创建我们的Spring 容器
 * 2. 加载/关联Spring容器的配置-按照注解的方式
 * 3. 完成Spring容器配置的bean的创建, 依赖注入
 * 4. 创建前端控制器 DispatcherServlet , 并让其持有Spring容器
 * 5. 当DispatcherServlet 持有容器, 就可以进行分发映射, 请小伙伴回忆我们实现SpringMVC底层机制
 * 6. 这里onStartup 是Tomcat调用, 并把ServletContext 对象传入
 */
public class HspWebApplicationInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {

        System.out.println("startup ....");
        //加载Spring web application configuration => 容器
        //自己 写过 HongSpringApplicationContext
        AnnotationConfigWebApplicationContext ac =
                new AnnotationConfigWebApplicationContext();
        //在ac中注册 HongConfig.class 配置类
        ac.register(HongConfig.class);
        ac.refresh();//完成bean的创建和配置

        //1. 创建注册非常重要的前端控制器 DispatcherServlet
        //2. 让DispatcherServlet 持有容器
        //3. 这样就可以进行映射分发, 回忆一下SpringMvc机制[自己实现过]
        //HongDispatcherServlet
        DispatcherServlet dispatcherServlet = new DispatcherServlet(ac);
        //返回了ServletRegistration.Dynamic对象
        ServletRegistration.Dynamic registration =
                servletContext.addServlet("app", dispatcherServlet);
        //当tomcat启动时,加载 dispatcherServlet
        registration.setLoadOnStartup(1);
        //拦截请求,并进行分发处理
        //这里在提示 / 和 /* => 在讲解 java web , 自己去看看.
        registration.addMapping("/");

    }
}

3.实现任务阶段 3- Tomcat Spring 容器关联, 并启动 Spring 容器

3.1 说明: Tomcat Spring 容器关联, 并启动 Spring 容器

3.2 分析+代码实现

代码实现
1.SpringApplication.java
public class HongSpringApplication {
    //这里我们会创建tomcat对象,并关联Spring容器, 并启动
    public static void run() {
        try {
            //创建Tomcat对象 HspTomcat
            Tomcat tomcat = new Tomcat();
            //1. 让tomcat可以将请求转发到spring web容器,因此需要进行关联
            //2. "/hong" 就是我们的项目的 application context , 就是我们原来配置tomcat时,指定的application context
            //3. "D:\\hspedu_springboot\\hsp-springboot" 指定项目的目录
            tomcat.addWebapp("/hong","D:\\hong_springboot\\hong-springboot");
            //设置9090
            tomcat.setPort(9090);
            //启动
            tomcat.start();
            //等待请求接入
            System.out.println("======9090====等待请求=====");
            tomcat.getServer().await();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

3.3debug 一下, 看看是否进行 Spring 容器的初始化工作, 可以看到 ac.refresh() 会将

HspConfig.class 中配置 Bean 实例化装入到容器中 .

 

 

结果:

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

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

相关文章

DeepLab V2学习笔记

DeepLab V2遇到的相关问题以及解决方法对于DeepLab V1的优化模型总结补充的一个小知识点ASPPLearning rate policy实验结果消融实验实验结果遇到的相关问题以及解决方法 和DeepLab V1中遇到的问题几乎没有什么太大的差别&#xff0c;在文章的引言部分作者提出了在语义分割中遇…

小程序商城拓展中小商户“线上时间”,系统化思维

在数字经济时代初期&#xff0c;新一代信息基础设施建设仍有待完善&#xff0c;在拓展“互联网”应用场景中应不断缩小“数字鸿沟”&#xff0c;逐渐向产业和行业下沉&#xff0c;让互联网巨头和中小微商户共享数字技术的红利&#xff0c;也因此将推动包括传统商户在内的数字化…

政务系统信息网络安全的风险评估

在当今信息时代的大形势下&#xff0c;互联网从普及到飞速发展&#xff0c;政务系统信息网络安全的问题也日益被重视起来。一方面&#xff0c;人们应该了解到政务系统信息网络安全的重要性&#xff1b;另一方面&#xff0c;人们对政务系统信息网络安全风险评估工作有所了解。有…

公厕智能感应皂液盒,无液手机信息提醒

传统式的洗手液一按一压。有时候经常控制不住量&#xff0c;一不小心就容易按多&#xff0c;弄得洗手台乱七八糟&#xff0c;满身也是黏哒哒的&#xff0c;特别让人糟心。刚做完饭&#xff0c;满手油腻&#xff0c;或是刚上完厕所&#xff0c;去按洗手液泵势必会弄脏它。 所以智…

【Python+Appium】开展自动化测试(一)

目录 前言 一&#xff0c;安装JDK&#xff0c;配置JDK环境变量 1&#xff0c;下载jdk 2&#xff0c;安装jdk 3&#xff0c;配置jdk环境变量 二&#xff0c;安装Android SDK&#xff0c;配置Android SDK环境 1&#xff0c;下载Android SDK 2&#xff0c;双击SDK Manager…

【日常记录】解决‘GLIBC_2.34‘ not found,并且gcc制定glibc版本编译

小荣的日常记录 &#x1f525;系列专栏&#xff1a;日常记录 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4c6;首发时间&#xff1a;&#x1f334;2022年11月21日&#x1f334; &#x1f36d;作者水平很有限&#xff0c;如果发现错…

DETR训练自己数据集心得

对QKV的理解&#xff0c;先废一下话... 计算流程参考&#xff1a;https://zhuanlan.zhihu.com/p/82312421 给定一组query&#xff0c;和当前输入样本input&#xff08;每个样本都有各自的key&#xff09;&#xff0c;经过空间变化后input→query。 计算query和key之间的相关…

深度学习与总结JVM专辑(二):垃圾回收基础(图文+代码)

垃圾回收基础概念什么是垃圾回收为什么要进行垃圾回收垃圾什么是垃圾你是垃圾吗&#xff1f;让我用算法来测测你。引用计数算法可达性分析算法对象引用对象&#xff0c;真的死了吗方法区回收废弃常量无用类垃圾回收算法回收类型分代收集理论标记清除算法&#xff08;Mark-Sweep…

【Hack The Box】linux练习-- Irked

HTB 学习笔记 【Hack The Box】linux练习-- Irked &#x1f525;系列专栏&#xff1a;Hack The Box &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4c6;首发时间&#xff1a;&#x1f334;2022年11月17日&#x1f334; &#x1f36…

[附源码]计算机毕业设计JAVA基于ssm的电子网上商城

[附源码]计算机毕业设计JAVA基于ssm的电子网上商城 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM my…

基于FPGA的PID控制器开发与实现

欢迎订阅《FPGA学习入门100例教程》、《MATLAB学习入门100例教程》 效果预览: 目录 一、理论基础 二、核心程序 三、测试结果

数据结构与算法之顺序表详解

标题&#xff1a;猜数字小游戏 作者&#xff1a;Ggggggtm 寄语&#xff1a;与其忙着诉苦&#xff0c;不如低头赶路&#xff0c;奋路前行&#xff0c;终将遇到一番好风景 文章目录&#xff1a; 一、顺序表的概念与结构 1、线性表的解释 2、顺序表概念解释 二、顺序表的思路及代码…

ERP系统三种部署方式的区别

ERP系统被认为是一种 "企业应用程序"&#xff0c;指的是为满足企业的软件需求和提高业务绩效而设计的软件。今天有许多不同的ERP系统可供使用&#xff0c;其范围很广&#xff0c;取决于企业的规模、功能和需求。ERP系统的类型根据其部署方式划分&#xff0c;包括云ER…

二、Redis分布式锁

一、什么是分布式锁 分布式锁是一种跨进程的&#xff0c;跨机器节点的一种互斥锁。保证在多个机器节点对共享资源访问的一个排他性。 分布式与单机情况下最大的不同在于分布式锁是多进程的而单机锁是单进程多线程的。 二、为什么需要分布式锁 与分布式锁相对就的是单机锁&…

BHQ-1 amine,1308657-79-5,BHQ染料通过FRET和静态猝灭的组合工作

英文名称&#xff1a;BHQ-1 amine 中文名称&#xff1a;BHQ-1 氨基 CAS&#xff1a;1308657-79-5 外观&#xff1a;深紫色粉末 分子式&#xff1a;C25H29N7O3 分子量&#xff1a;475.55 结构式&#xff1a; 溶解性&#xff1a;溶于大部分有机溶剂&#xff0c;溶于水 储存…

luffy-(13)

内容概览 支付宝支付介绍支付宝支付二次封装订单相关表设计生成订单接口支付前端支付宝回调接口 支付宝支付介绍 """ 项目中有需要在线支付功能,可以使用支付宝支付(沙箱环境)微信支付(需要有备案过的域名)云闪付我们的项目以支付宝支付为例支付流程使用官方…

【动手学深度学习】关于“softmax回归的简单实现”报错的解决办法(含源代码)

目录&#xff1a;关于“softmax回归的简单实现”报错的解决办法一、前言二、实现步骤2.1 导包2.2 初始化模型参数2.3 重新审视Softmax的实现2.4 优化算法2.5 训练2.6 源代码三、问题出现四、问题的解决五、再跑代码六、改正后的函数源代码一、前言 在之前的学习中&#xff0c;…

题库系统(公众号免费调用)

题库系统(公众号免费调用) 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 查题校园题库&#xff1a;查题校园题库后台&#xff0…

arthas 源码构建

arthas 源码构建 git下载代码 git clone https://github.com/alibaba/arthas.git 若github被墙&#xff0c;可以在gitee搜索下载 maven clean 可以在项目目录执行 mvn clean &#xff0c; ide可以执行界面执行 maven package 可以在项目目录执行mvn package 问题记录 ja…

四肽Suc-AAPD-对硝基苯胺,165174-58-3

粒酶B底物succ - aapd - pna。也被ICE劈开了。 编号: 177581中文名称: 四肽Suc-Ala-Ala-Pro-Asp-对硝基苯胺CAS号: 165174-58-3单字母: Suc-AAPD-pNA三字母: Suc-Ala-Ala-Pro-Asp-pNA氨基酸个数: 4分子式: C25H32O11N6平均分子量: 592.56精确分子量: 592.21等电点(PI): -pH7.0时…