位置: IT常识 - 正文

给她讲最爱的SpringBoot源码(给最爱的他)

编辑:rootadmin
1 Spring boot源码环境构建 推荐环境: idea:2020.3 gradle:版本gradle-6.5.1 jdk:1.8 注意!idea和gradle的版本有兼容性问题,要注意搭配 1.1 Spring boot源码下载 1、从github获取源码,网址: https://github ... 1 Spring boot源码环境构建

推荐整理分享给她讲最爱的SpringBoot源码(给最爱的他),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:给最爱的人讲故事,给最爱的说话歌词,写给最爱的她的说说,给最爱的人讲故事,给最爱的人讲故事,给最爱的说话歌词,给最爱的那个他,给最爱的那个他,内容如对您有帮助,希望把文章链接给更多的朋友!

推荐环境:

idea:2020.3

gradle:版本gradle-6.5.1

jdk:1.8

注意!idea和gradle的版本有兼容性问题,要注意搭配

1.1 Spring boot源码下载

1、从github获取源码,网址:

https://github.com/spring-projects/spring-boot

我们要搭建的是2.4.3.RELEASE版本,所以点击release 之后在tags查找相应版本或者访问

https://github.com/spring-projects/spring-boot/releases/tag/v2.4.3

找到 后点击sourcecode下载源码压缩包

目录结构

Spring-boot-project 核心代码,代码量很多(197508 行)Spring-boot-tests 测试代码

2、直接用提供的源码包(推荐)

将源码导入到idea。漫长的等待……

1.2 Spring boot源码编译

1、环境配置

推荐配置:

2、开始gradle构建

使用idea的build,不要用gradle的任务

看到下面的BUILE SUCESSFUL表示成功

1.3 Spring boot冒烟测试

在springboot-boot-tests模块下很多冒烟测试的,会拖慢上面的编译,只留下了一个:

spring-boot-smoke-test-hibernate52工程来进行冒烟测试,打开Hibernate52Application.java文件,直接执行main方法启动springboot,成功!

org.springframework.boot.tests.hibernate52.Hibernate52Application

package org.springframework.boot.tests.hibernate52;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class Hibernate52Application {public static void main(String[] args) {SpringApplication.run(Hibernate52Application.class, args);}}

执行run

console中出现我们熟悉的图标。

2 Spring boot源码深度剖析引言使用过SpringBoot开发项目的读者应该都能够感觉到SpringBoot的开发完成后,只需要通过执行一个main方法就可以将整个web项目启动无需将项目的jar文件放在tomcat下,然后启动tomcat,进而启动项目。除此之外,好多依赖的jar包也无需我们再进行手动配置,减少了配置,同时也减少了许多xml文件的配置,大大简化了我们的开发过程那么springboot在启动的时候到底做了哪些事情?2.1 Spring boot启动流程剖析

第一步:new SpringApplication(primarySources)

第二步:run!

2.1.1 Spring boot启动流程剖析

Debug一下,追踪一下整个启动过程

main方法作为程序的入口,执行SpringApplication.run(),传入参数是启动类的class对象

1)Spring boot源码入口@SpringBootApplicationpublic class Hibernate52Application {public static void main(String[] args) {SpringApplication.run(Hibernate52Application.class, args);}}

跟踪run方法;进入到

参数一可支持多个主要资源。

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {return run(new Class<?>[] { primarySource }, args);}

继续进入到run方法

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {return new SpringApplication(primarySources).run(args);}2)构造器(new)//方法目标//1、初始化资源加载器(classloader)//2、处理primarySources//3、web应用类型推断 (web、reactive、servlet)//4、通过spring.factories加载配置类并初始化监听器 (SPI) 【重点】//5、提取主类public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {//null;资源加载器,用来获取 Resource 和 classLoader 以及加载资源this.resourceLoader = resourceLoader;Assert.notNull(primarySources, "PrimarySources must not be null");//存放主加载类;set中可同时创建多个Application,最后要解析这个来源上的注解this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));//推断 web 类型:servlet 或 reactivethis.webApplicationType = WebApplicationType.deduceFromClasspath();//0个,从spring.factories中找出Bootstrapper对应的属性this.bootstrappers = new ArrayList<>(getSpringFactoriesInstances(Bootstrapper.class));//7个,设置初始化器,从spring.factories中找出ApplicationContextInitializer对应的属性setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));//9个,设置监听器 从spring.factories中找出ApplicationListener对应的属性setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));//找出主函数main的类this.mainApplicationClass = deduceMainApplicationClass();}

上面 的代码最终会调用到getSpringFactoriesInstances,从spring.factories加载属性配置

加载核心源码如下

下面代码

首先会用classLoader加载类路径下的所有spring.factories的配置内容,loadSpringFactories方法将返回一个key=接口名,value=实现类集合的Map结构

private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) { // 先试着取缓存Map<String, List<String>> result = cache.get(classLoader);if (result != null) {return result;}result = new HashMap<>();try { // 获取所有spring.factories的URL(3个地方)Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION); // 遍历URLwhile (urls.hasMoreElements()) {URL url = urls.nextElement();UrlResource resource = new UrlResource(url); // 加载每个URL中的properties配置Properties properties = PropertiesLoaderUtils.loadProperties(resource);for (Map.Entry<?, ?> entry : properties.entrySet()) {String factoryTypeName = ((String) entry.getKey()).trim(); // 将实现类的配置按照","符号分割开String[] factoryImplementationNames =StringUtils.commaDelimitedListToStringArray((String) entry.getValue());for (String factoryImplementationName : factoryImplementationNames) { // 逐个添加到接口对应的集合当中result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>()).add(factoryImplementationName.trim());}}}// Replace all lists with unmodifiable lists containing unique elementsresult.replaceAll((factoryType, implementations) -> implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList))); //加入缓存cache.put(classLoader, result);}catch (IOException ex) {throw new IllegalArgumentException("Unable to load factories from location [" +FACTORIES_RESOURCE_LOCATION + "]", ex);}return result;}

主要的spring.factories

spring-boot-2.4.3/spring-boot-project/spring-boot-autoconfigure/build/resources/main/META-INF/spring.factoriesspring-boot-2.4.3/spring-boot-project/spring-boot/build/resources/main/META-INF/spring.factoriesspring-beans-5.3.4.jar!/META-INF/spring.factories

构造器流程总结

1、处理资源加载器、主要资源primarySources

2、web应用类型推断

3、从spring.factories中找出引导包装器、初始化器、监听器

4、设置应用程序主类

3)boot运行(run)

发布事件

打印banner

初始化ioc容器,启动tomcat

七大步骤

//七大步骤public ConfigurableApplicationContext run(String... args) {//计时器StopWatch stopWatch = new StopWatch();stopWatch.start(); //开始计时// 创建启动上下文对象DefaultBootstrapContext bootstrapContext = createBootstrapContext();// 可配置的程序容器ConfigurableApplicationContext context = null;// 设置属性 不重要configureHeadlessProperty();// 第一步:获取并启动监听器 从spring.factories文件中加载【测试点】SpringApplicationRunListeners listeners = getRunListeners(args);//监听器发布ApplicationStartingEvent 事件.listeners.starting(bootstrapContext, this.mainApplicationClass);try {// 对参数进行包装(ApplicationArguments)ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);//第二步:准备应用程序环境【关键点】ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);// 配置忽略bean的信息(不重要)configureIgnoreBeanInfo(environment);//第三步: 打印banner(可自定义,参考讲义)【关键点】Banner printedBanner = printBanner(environment); // 第四步:创建spring容器context = createApplicationContext();context.setApplicationStartup(this.applicationStartup);//第五步:准备 applicationContextprepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);//第六步:ioc的refresh创建容器,初始化bean,tomcat也在这里被启动起来 【关键点】refreshContext(context); //第七步:上下文刷新后触发(空方法)afterRefresh(context, applicationArguments);stopWatch.stop();//停止计时if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}// 发布started事件listeners.started(context);//执行runner的run方法 【测试点】callRunners(context, applicationArguments);} catch (Throwable ex) {// 异常处理handleRunFailure(context, ex, listeners);throw new IllegalStateException(ex);}try {// 触发running事件listeners.running(context);} catch (Throwable ex) {handleRunFailure(context, ex, null);throw new IllegalStateException(ex);}// 返回最终构建的容器对象return context;}2.1.2 Spring boot七大步骤详解1)获取并启动监听器给她讲最爱的SpringBoot源码(给最爱的他)

这里的启动监听就是我们需要监听SpringBoot的启动流程监听,实现SpringApplicationRunListener类即可监听

//获取spring.factories中 key为SpringApplicationRunListener的对象实例。private SpringApplicationRunListeners getRunListeners(String[] args) {Class<?>[] types = new Class<?>[]{SpringApplication.class, String[].class};// 通过从 spring.factories 中获取 SpringApplicationRunListener 类型的配置类return new SpringApplicationRunListeners(logger,getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),this.applicationStartup);}

查看具体SpringApplicationRunListener都有哪些方法

package org.springframework.boot;import org.springframework.context.ApplicationContext;import org.springframework.context.ConfigurableApplicationContext;import org.springframework.core.env.ConfigurableEnvironment;import org.springframework.core.io.support.SpringFactoriesLoader;public interface SpringApplicationRunListener {/** * Called immediately when the run method has first started. Can be used for very * early initialization. * @param bootstrapContext the bootstrap context *///当调用run方法后会立即调用,可以用于非常早期的初始化default void starting(ConfigurableBootstrapContext bootstrapContext) {starting();}/** * Called immediately when the run method has first started. Can be used for very * early initialization. * @deprecated since 2.4.0 in favor of {@link #starting(ConfigurableBootstrapContext)} */@Deprecateddefault void starting() {}/** * Called once the environment has been prepared, but before the * {@link ApplicationContext} has been created. * @param bootstrapContext the bootstrap context * @param environment the environment *///环境准备好之后调用default void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,ConfigurableEnvironment environment) {environmentPrepared(environment);}/** * Called once the environment has been prepared, but before the * {@link ApplicationContext} has been created. * @param environment the environment * @deprecated since 2.4.0 in favor of * {@link #environmentPrepared(ConfigurableBootstrapContext, ConfigurableEnvironment)} */@Deprecateddefault void environmentPrepared(ConfigurableEnvironment environment) {}/** * Called once the {@link ApplicationContext} has been created and prepared, but * before sources have been loaded. * @param context the application context *///在加载资源之前,ApplicationContex准备好之后调用default void contextPrepared(ConfigurableApplicationContext context) {}/** * Called once the application context has been loaded but before it has been * refreshed. * @param context the application context *///在加载应用程序上下文但在其刷新之前调用default void contextLoaded(ConfigurableApplicationContext context) {}/** * The context has been refreshed and the application has started but * {@link CommandLineRunner CommandLineRunners} and {@link ApplicationRunner * ApplicationRunners} have not been called. * @param context the application context. * @since 2.0.0 *//** * 上下文已经刷新且应用程序已启动且所有{@link CommandLineRunner commandLineRunner} * 和{@link ApplicationRunner ApplicationRunners}未调用之前调用 */default void started(ConfigurableApplicationContext context) {}/** * Called immediately before the run method finishes, when the application context has * been refreshed and all {@link CommandLineRunner CommandLineRunners} and * {@link ApplicationRunner ApplicationRunners} have been called. * @param context the application context. * @since 2.0.0 *//** * 当应用程序上下文被刷新并且所有{@link CommandLineRunner commandLineRunner} * 和{@link ApplicationRunner ApplicationRunners}都已被调用时,在run方法结束之前立即调用。 */default void running(ConfigurableApplicationContext context) {}/** * Called when a failure occurs when running the application. * @param context the application context or {@code null} if a failure occurred before * the context was created * @param exception the failure * @since 2.0.0 *///在启动过程发生失败时调用default void failed(ConfigurableApplicationContext context, Throwable exception) {}}2)准备应用程序环境

创建并配置SpringBooty应用将要使用的Environment

//不看细节,看返回的环境数据即可//创建并配置SpringBooty应用将要使用的Environment//过程如下://1、创建配置环境 ConfigurableEnvironment//2、加载属性文件资源//3、配置监听private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {// 根据不同的web类型创建不同实现的Environment对象ConfigurableEnvironment environment = getOrCreateEnvironment();// 配置环境configureEnvironment(environment, applicationArguments.getSourceArgs());ConfigurationPropertySources.attach(environment);// 发送环境已准备完成事件listeners.environmentPrepared(bootstrapContext, environment);DefaultPropertiesPropertySource.moveToEnd(environment);// 根据命令行参数中spring.profiles.active属性配置Environment对象中的activeProfile(比如dev、prod、test)configureAdditionalProfiles(environment);// 绑定环境中spring.main属性绑定到SpringApplication对象中bindToSpringApplication(environment);// 如果用户使用spring.main.web-application-type属性手动设置了webApplicationTypeif (!this.isCustomEnvironment) {// 将环境对象转换成用户设置的webApplicationType相关类型,他们是继承同一个父类,直接强转environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,deduceEnvironmentClass());}ConfigurationPropertySources.attach(environment);return environment; //环境查看(控制台)}

查看环境

3)控制台打印Bannerprivate Banner printBanner(ConfigurableEnvironment environment) {// banner模式,可以是console、log、offif (this.bannerMode == Banner.Mode.OFF) {return null;}ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader: new DefaultResourceLoader(null);SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);//日志打印bannerif (this.bannerMode == Mode.LOG) {return bannerPrinter.print(environment, this.mainApplicationClass, logger);}//控制台打印bannerreturn bannerPrinter.print(environment, this.mainApplicationClass, System.out);}

最终打印

通过org.springframework.boot.ResourceBanner#printBanner

@Overridepublic void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) {try {String banner = StreamUtils.copyToString(this.resource.getInputStream(),environment.getProperty("spring.banner.charset", Charset.class, StandardCharsets.UTF_8));for (PropertyResolver resolver : getPropertyResolvers(environment, sourceClass)) {banner = resolver.resolvePlaceholders(banner);}out.println(banner);//此处打印}catch (Exception ex) {logger.warn(LogMessage.format("Banner not printable: %s (%s: '%s')", this.resource, ex.getClass(),ex.getMessage()), ex);}}

截图如下

4)创建应用上下文对象protected ConfigurableApplicationContext createApplicationContext() {return this.applicationContextFactory.create(this.webApplicationType);}

调用到下面

public interface ApplicationContextFactory {/** * A default {@link ApplicationContextFactory} implementation that will create an * appropriate context for the {@link WebApplicationType}. *///返回一个应用程序上下文ApplicationContextFactory DEFAULT = (webApplicationType) -> {try {switch (webApplicationType) {case SERVLET: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);}};5)准备应用上下文

核心代码如下

/** * Spring容器准备 */private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments, Banner printedBanner) {context.setEnvironment(environment);//设置环境postProcessApplicationContext(context);//设置上下文// 执行所有ApplicationContextInitializer对象的initialize方法(这些对象是通过读取spring.factories加载)applyInitializers(context);//设置初始化工作(不用看)// 发布上下文准备完成事件到所有监听器listeners.contextPrepared(context);//触发监听器bootstrapContext.close(context);if (this.logStartupInfo) { //日志操作logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);}// 获取工厂 DefaultListableBeanFactoryConfigurableListableBeanFactory beanFactory = context.getBeanFactory();//注册单例对象beanFactory.registerSingleton("springApplicationArguments", applicationArguments);if (printedBanner != null) {//注册banner单例对象beanFactory.registerSingleton("springBootBanner", printedBanner);}if (beanFactory instanceof DefaultListableBeanFactory) {//是否覆盖bean((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}if (this.lazyInitialization) { //是否懒加载context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());}// Load the sourcesSet<Object> sources = getAllSources();Assert.notEmpty(sources, "Sources must not be empty");//加载(业务类的注解需要扫描) bean到上下文load(context, sources.toArray(new Object[0]));// 发送上下文加载完成事件listeners.contextLoaded(context);}6)刷新应用程序上下文

ioc容器初始化

重要!

tomcat的启动在这里!

//核心方法private void refreshContext(ConfigurableApplicationContext context) {// ……// 开始执行启动容器(调用模板方法)refresh((ApplicationContext) context);}

扩展问题:

如果在springboot里使用了web容器,它是如何启动的?

refreshContext 里面,沿着 refresh - onRefresh,注意是 ServletWebServerApplicationContext的

我们说,在普通的spring里onRefresh是个空方法,留给子类去实现,那么,

看看这个 ServletWebServerApplicationContext 实现类它的 onRefresh偷偷干了些啥见不得人的事?……

7)容器回调方法

空方法

protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) {}

run方法启动后主要做如下几件事情:

1、发出启动结束事件

2、执行实现ApplicationRunner、CommandLineRunner的run方法3、发布应用程序已启动(ApplicationStartedEvent)事件

4、异常处理

小疑问:

boot启动了一个web,那么一定有一个DispacherServlet,它是啥时候被加载的呢???

提示:

@EnableAutoConfiguration 注解的spi,在spring-boot-autoconfigure的spring.factories里

EnableAutoConfiguration的加载类里有个:DispatcherServletAutoConfiguration 做了自动装配

秘密就藏在这货里

那自动装配又是什么鬼呢?除了DS,还有各种starter,怎么加载的呢?下节课继续……

2.2 boot自定义Banner

banner自动生成工具,ascii文字展示

http://www.network-science.de/ascii/

Spring boot启动如下

在路径

\spring-boot-tests\spring-boot-smoke-tests\spring-boot-smoke-test-hibernate52\src\main\resources

下创建banner.txt(注意:文件名称不能变,否则无法加载)

banner.txt内容如下

88b d88 88888888ba888b d888 88 "8b ,d 88`8b d8'88 88 ,8P 88 88 `8b d8' 88 8b d8 88aaaaaa8P' ,adPPYba, ,adPPYba, MM88MMM 88 `8b d8' 88 `8b d8' 88""""""8b, a8" "8a a8" "8a 88 88 `8b d8' 88 `8b d8' 88 `8b 8b d8 8b d8 88 88 `888' 88 `8b,d8' 88 a8P "8a, ,a8" "8a, ,a8" 88, 88 `8' 88 Y88' 88888888P" `"YbbdP"' `"YbbdP"' "Y888 d8' d8' 2.3 面试题

1、Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的

启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解:

@SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。@EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。

​ 组合了

@AutoConfigurationPackage@Import(AutoConfigurationImportSelector.class)@ComponentScan:Spring组件扫描

2、Spring Boot 自动配置原理是什么?

注解 @EnableAutoConfiguration, @Configuration, @ConditionalOnClass 就是自动配置的核心,

@EnableAutoConfiguration 给容器导入META-INF/spring.factories 里定义的自动配置类。

筛选有效的自动配置类。

每一个自动配置类结合对应的 xxx.java 读取配置文件进行自动配置功能

3、Spring Boot 中的 starter 到底是什么 ?

首先,这个 Starter 并非什么新的技术点,基本上还是基于 Spring 已有功能来实现的。首先它提供了一个自动化配置类,一般命名为 XXXAutoConfiguration ,在这个配置类中通过条件注解来决定一个配置是否生效(条件注解就是 Spring 中原本就有的),然后它还会提供一系列的默认配置,也允许开发者根据实际情况自定义相关配置,然后通过类型安全的属性注入将这些配置属性注入进来,新注入的属性会代替掉默认属性。正因为如此,很多第三方框架,我们只需要引入依赖就可以直接使用了。当然,开发者也可以自定义 Starter

4、运行 Spring Boot 有哪几种方式?

1)打包用命令或者放到容器中运行

2)用 Maven/ Gradle 插件运行

3)直接执行 main 方法运行

本文由传智教育博学谷教研团队发布。

如果本文对您有帮助,欢迎关注和点赞;如果您有任何建议也可留言评论或私信,您的支持是我坚持创作的动力。

转载请注明出处!

本文链接地址:https://www.jiuchutong.com/zhishi/304667.html 转载请保留说明!

上一篇:python函数接收不同类型的参数(python语言接收信息的内置函数)

下一篇:python序列解包的使用(python 序列化)

  • 苹果x深色模式的打开方法是什么(iphone x深色模式)

    苹果x深色模式的打开方法是什么(iphone x深色模式)

  • iphone11怎么关闭应用程序(iphone11怎么关闭非原装电池通知)

    iphone11怎么关闭应用程序(iphone11怎么关闭非原装电池通知)

  • 华为白屏死机如何处理(华为手机白屏一下黑屏不能开机了)

    华为白屏死机如何处理(华为手机白屏一下黑屏不能开机了)

  • ipad2慢了怎么办(ipad2运行慢卡怎么办)

    ipad2慢了怎么办(ipad2运行慢卡怎么办)

  • 苹果耳机三代充电线怎么用(苹果耳机三代充电仓丢了可以配的到吗)

    苹果耳机三代充电线怎么用(苹果耳机三代充电仓丢了可以配的到吗)

  • 电脑显示屏变粉色了怎么办(电脑显示器突然变粉)

    电脑显示屏变粉色了怎么办(电脑显示器突然变粉)

  • 无线网需要认证是怎么回事(无线网需要认证但是打不开)

    无线网需要认证是怎么回事(无线网需要认证但是打不开)

  • lld al10是什么型号(lldal10是什么型号多少钱)

    lld al10是什么型号(lldal10是什么型号多少钱)

  • 抖音怎么把很多照片做成视频(抖音怎么把很多个视频截取到一个上面)

    抖音怎么把很多照片做成视频(抖音怎么把很多个视频截取到一个上面)

  • 华为p30和p30lite区别(华为P30和小米13对比)

    华为p30和p30lite区别(华为P30和小米13对比)

  • 华为mate30有智能语音吗(华为mate30有智能充电吗?)

    华为mate30有智能语音吗(华为mate30有智能充电吗?)

  • 抖音点完赞为什么会自动取消(抖音点完赞为什么我喜欢里面没有)

    抖音点完赞为什么会自动取消(抖音点完赞为什么我喜欢里面没有)

  • b类地址标准子网掩码(b类地址例子)

    b类地址标准子网掩码(b类地址例子)

  • 怎么在word新建文档(怎么在word新建一个文件夹)

    怎么在word新建文档(怎么在word新建一个文件夹)

  • 乐视手机账号怎么注销(乐视手机账号怎么登录)

    乐视手机账号怎么注销(乐视手机账号怎么登录)

  • 手机收藏的图片在哪(手机收藏的图片在哪里可以找出来)

    手机收藏的图片在哪(手机收藏的图片在哪里可以找出来)

  • 腾讯地图怎么添加店铺位置(腾讯地图怎么添加自己的公司)

    腾讯地图怎么添加店铺位置(腾讯地图怎么添加自己的公司)

  • 自动定时开关怎么设置(自动定时开关怎么接线)

    自动定时开关怎么设置(自动定时开关怎么接线)

  • mmexport什么意思

    mmexport什么意思

  • 微信聊天记录怎么恢复?1分钟找回3年前记录(微信聊天记录怎么导出来成文件)

    微信聊天记录怎么恢复?1分钟找回3年前记录(微信聊天记录怎么导出来成文件)

  • 一加怎么查激活时间(一加手机如何查激活)

    一加怎么查激活时间(一加手机如何查激活)

  • 如何把爱奇艺的视频保存到相册(如何把爱奇艺的自动续费关掉)

    如何把爱奇艺的视频保存到相册(如何把爱奇艺的自动续费关掉)

  • 华为相册图片更改顺序(华为手机更改相片存储位置)

    华为相册图片更改顺序(华为手机更改相片存储位置)

  • qq被冻结怎么办手机(qq涉嫌违规注册qq被冻结怎么办)

    qq被冻结怎么办手机(qq涉嫌违规注册qq被冻结怎么办)

  • 半自动洗衣机怎么清洗污垢(半自动洗衣机怎么放水)

    半自动洗衣机怎么清洗污垢(半自动洗衣机怎么放水)

  • 易企秀怎么上传音乐(易企秀怎么上传视频)

    易企秀怎么上传音乐(易企秀怎么上传视频)

  • 苹果gsx查询是什么(苹果查询gsc是什么意思)

    苹果gsx查询是什么(苹果查询gsc是什么意思)

  • 微信申诉没有好友辅助验证怎么办(微信申诉没有好友辅助)

    微信申诉没有好友辅助验证怎么办(微信申诉没有好友辅助)

  • 外地预缴税金
  • 房子税票是什么意思
  • 进项税跟增值税
  • 买一赠一的税务怎么算
  • 未达起征点增值税能否开票
  • 房租雇东不开发票只有收据怎么处理?
  • 盈余公积是否必要交税
  • 原始凭证和记账凭证的作用分别是什么
  • 出口退税发票未稽核可以申报退税吗
  • 税务局不给注销税务
  • 固定资产抵债要交税吗怎么交
  • 销售机械设备的税率是多少
  • 所得税汇算清缴表在哪里打印
  • 跨年度取得增值税发票能否抵扣?
  • 药企会计租金进项税不能抵扣
  • 2017年个税税率表及个税计算公式
  • 对于甲供工程,施工方销售额不包括建设方提供的材料款。那么该销售额是否包括设备及动力款?
  • 单位社保扣款
  • 广告费扣税
  • 非金融企业利息费用的扣除标准
  • 领用自产产品用于在建工程入账金额
  • 高新企业研发项目
  • 新企业购买金税盘
  • 多抵扣的进项如何做分录
  • 年末应计提坏账准备为什么是负数
  • 事业单位授权支付一体化退库
  • macOS 11 Big Sur beta 4值得升级吗?macOS 11 Big Sur beta 4更新详解
  • 商品结转成本后怎么做账
  • 收到单据
  • php使用自定义函数编程求半径r的圆的周长和面积
  • 错误解决方法
  • dac模型
  • linux调试工具有哪些
  • 设备购买与租赁的分析中,购买优于租赁的条件是
  • 织梦网站怎么添加关键词
  • 购买方销项负数发票怎么抵扣
  • 盈余公积转增资本所有者权益会变吗
  • 基本工资是包括哪些内容
  • SQL 联合查询与XML解析实例详解
  • 如何分析成本费用高
  • 代销商品税率是多少
  • 财产租赁合同印花税双方都要交吗
  • 新成立企业多长时间可以销售小微企业
  • 暂估和开票的差异 erp处理
  • 进项税怎么记账
  • 委托代理进口账务处理
  • 房地产公司退房款怎么做账
  • 主营业务收入增加计入借方还是贷方
  • 购建固定资产属于投资活动吗
  • 如何解绑企业微信绑定的邮箱
  • 房地产开发企业电费做什么科目
  • 资本公积金什么时候提取
  • mysql怎么备份数据库命令
  • win7电脑初始化
  • xp系统没有声音没有音频设备
  • 磁盘清理后文件还在吗?
  • 双启动子存在的意义
  • centos7搜索
  • 如何解决电脑蓝屏0X0000007B
  • U盘安装centos8
  • win7删除windows.old
  • xp系统1
  • mac打开safari快捷键
  • tcp半连接和全连接
  • 鼠标点击关闭按钮没反应
  • mac内存管理在哪里
  • windows10无法关闭
  • win7未能启动怎么办
  • Win10控制面板打不开
  • Win10桌面图标没有了
  • linux计划任务每天九点
  • javascript程序代码
  • dos命令 /b
  • jquery点击移动div
  • android ui线程和主线程的区别
  • java获取两个日期间的所有月份
  • jQuery AjaxUpload 上传图片代码
  • 税务行业微信缴税项目是什么
  • 国税系统升级后怎么添加办税人
  • 江西省抚州市黎川县洵口镇
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设