SpringBoot启动过程

SpringBoot启动

这里写图片描述

Spring Boot通常有一个名为*Application的入口类,在入口类里有一个main方法,这个main方法其实就是一个标准的java应用的入口方法。
在main方法中使用SpringApplication.run方法启动SpringBoot应用项目。


其中@SpringBootApplication是Spring Boot的核心注解,它是一个组合注解:

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这里写图片描述

其中@SpringBootApplication注解主要组合了@Configuration、@EnableAutoConfiguration、@ComponentScan。

如果不使用@SpringBootApplication注解,则可以使用在入口类上直接使用@Configuration、@EnableAutoConfiguration、@ComponentScan也能达到相同效果。


其中几个注解的作用大致说一下:

@Configuration:是做类似于spring xml 工作的注解 标注在类上,类似与以前的**.xml配置文件。

@EnableAutoConfiguration:spring boot自动配置时需要的注解,会让Spring Boot根据类路径中的jar包依赖为当前项目进行自动配置。同时,它也是一个组合注解。

 
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

这里写图片描述

在@EnableAutoConfiguration中用了@Import注解导入EnableAutoConfigurationImportSelector类,而EnableAutoConfigurationImportSelector就是自动配置关键。

@Import:Spring4.2之前只支持导入配置类
        Spring4.2之后支持导入普通的java类,并将其声明成一个bean

@ComponentScan:告诉Spring 哪个packages 的用注解标识的类 会被spring自动扫描并且装入bean容器。

SpringBoot的自动配置:SpringBoot的一大特色就是自动配置,例如:添加了spring-boot-starter-web依赖,会自动添加Tomcat和SpringMVC的依赖,SpringBoot会对Tomcat和SpringMVC进行自动配置。
又例如:添加了spring-boot-starter-data-jpa依赖,SpringBoot会自动进行JPA相关的配置。

SpringBoot会自动扫描@SpringBootApplication所在类的同级包以及下级包的Bean(如果为JPA项目还可以扫描标注@Entity的实体类),所以建议入口类放置在最外层包下。


spring-boot启动过程:

 
  • 11
  • 12
  • 13
  • 14
  • 15

这里写图片描述

在这里调用了SpringApplication的静态run方法,并将Application类对象和main方法的参数args作为参数传递了进去。


SpringApplication run方法:

 
  • 5

这里写图片描述

在这个静态方法中,创建并构造了SpringApplication对象,并调用该对象的run方法。

构造SpringApplication对象:

 
  • 4

这里写图片描述

主要是对一些属性附上初始值,关键还在与SpringApplication对象的initialize方法。

 
  • 2

这里写图片描述

SpringApplication类中的构造函数中调用initialize方法,初始化SpringApplication对象的成员变量sources,webEnvironment,initializers,listeners,mainApplicationClass。

 
  • 2

sources: 我们传给SpringApplication.run方法的参数。

webEnvironment:

这里写图片描述

可以看到webEnvironment是一个boolean,该成员变量用来表示当前应用程序是不是一个Web应用程序。通过在classpath中查看是否存在WEB_ENVIRONMENT_CLASSES这个数组中所包含的类,如果存在那么当前程序即是一个Web应用程序,反之则不是。

 
  • 2

initializers:

    这里关键是调用SpringApplication对象中的getSpringFactoriesInstances方法,来获取ApplicationContextInitializer类型对象的列表。

 
  • 2

这里写图片描述

在该方法中,首先通过调用SpringFactoriesLoader.loadFactoryNames(type,classLoader)来获取所有Spring Factories的名字(在包spring-boot-版本.jar下)。

 
  • 2

这里写图片描述

这里写图片描述

可以看到,是从一个名字叫spring.factories的资源文件中,读取key为org.springframework.context.ApplicationContextInitializer的value。而spring.factories的部分内容如下:

 
  • 2

这里写图片描述

这里写图片描述

我们从上面的spring.factories的资源文件中可以看到,得到的是     ConfigurationWarningsApplicationContextInitializer
ContextIdApplicationContextInitializer
DelegatingApplicationContextInitializer
ServerPortInfoApplicationContextInitializer这四个类的名字。

然后调用createSpringFactoriesInstances方法根据读取到的名字创建ApplicationContextInitializer实例(框起来的两行代码执行创建ApplicationContextInitializer实例)。

 
  • 7

这里写图片描述

最后会将创建好的对象列表排序并返回。

SpringApplication对象的成员变量initalizers就被初始化为,ConfigurationWarningsApplicationContextInitializer,ContextIdApplicationContextInitializer,DelegatingApplicationContextInitializer,ServerPortInfoApplicationContextInitializer这四个类的对象组成的list(这是默认的成员变量initalizers初始化)。

下面是几个类的作用,这里不做详细介绍,以后会有详解介绍:

 
  • 6

这里写图片描述

listeners:

listeners成员变量,是一个ApplicationListener<?>类型对象的集合。可以看到获取该成员变量内容使用的是跟成员变量initializers一样的方法,只不过传入的类型从ApplicationContextInitializer.class变成了ApplicationListener.class。


所以重点看spring.factories中取key为org.springframework.context.ApplicationListener的value有那些类:

 
  • 5

这里写图片描述

也就是说,listener最终会被初始化为
ClearCachesApplicationListener
ParentContextCloserApplicationListener  FileEncodingApplicationListener
AnsiOutputApplicationListener           ConfigFileApplicationListener
DelegatingApplicationListener           LiquibaseServiceLocatorApplicationListener
ClasspathLoggingApplicationListener     LoggingApplicationListener
这几个类的对象组成的list。

何时触发,这里不做详解,等事件出现时,做详细说明(这里有一张网上的图,可以了解):

 
  • 10

这里写图片描述

mainApplicationClass:

在deduceMainApplicationClass方法中,通过获取当前调用栈,找到入口方法main所在的类,并将其复制给SpringApplication对象的成员变量mainApplicationClass。在我们的例子中mainApplicationClass即是我们自己编写的Application类。

 
  • 2

这里写图片描述

现在已经构造完SpringApplication对象了,之后就是调用该对象的run方法来运行spring boot项目。

run方法:

这里写图片描述

StopWatch是来自org.springframework.util的工具类,可以用来方便的记录程序的运行时间。

 
  • 2

这里写图片描述

设置系统属性java.awt.headless,在我们的例子中该属性会被设置为true,因为我们开发的是服务器程序,一般运行在没有显示器和键盘的环境,但是还是需要相关一些数据,这样我们就可以这样设置系统属性为headless模式。

 
  • 2

这里写图片描述

run方法中,加载了一系列SpringApplicationRunListener对象,在创建和更新ApplicationContext方法前后分别调用了listeners对象的started方法和finished方法,并在创建和刷新ApplicationContext时,将listeners作为参数传递到了createAndRefreshContext方法中,以便在创建和刷新ApplicationContext的不同阶段,调用listeners的相应方法以执行操作。所以,所谓的SpringApplicationRunListeners实际上就是在SpringApplication对象的run方法执行的不同阶段,去执行一些操作,并且这些操作是可配置的.

创建ApplicationContext时调用startint方法

 
  • 4

这里写图片描述

更新ApplicationContext方法时调用finished方法:

 
  • 2

这里写图片描述

加载SpringApplicationRunListener,方式和initializers,listeners相同,所以我们可以在spring.factories中取key为org.springframework.boot.SpringApplicationRunListener的value可以看出加载了哪些类:

 
  • 2

这里写图片描述

可以看出加载的是org.springframework.boot.context.event.EventPublishingRunListener类

 
  • 2

这里写图片描述

EventPublishingRunListener:

 
  • 2

这里写图片描述

EventPublishingRunListener对象在初始化时候将SpringApplication对象的成员变量listeners全都保存下来。

等到自己的public方法被调用时,发布相应的事件,或执行相应的操作。

RunListener是在SpringApplication对象的run方法执行到不同的阶段时,发布相应的event给SpringApplication对象的成员变量listeners中记录的事件监听器。


SpringApplicationRunListeners相关的类结构:

 
  • 9

这里写图片描述

默认情况下,调用listeners的started方法,发布了ApplicationStartedEvent时,我们已经加载的事件监听器都做了什么操作,(实现了ApplicationListener接口的类,并且事件类型是ApplicationStartingEvent类型)。

 
  • 2

这里写图片描述

这里写图片描述

在默认情况下,classpath中不存在liquibase,所以不执行任何操作。

LoggingApplicationListener监听ApplicationStartedEvent,会根据classpath中的类情况创建相应的日志系统对象,并执行一些初始化之前的操作;

 
  • 4

这里写图片描述

默认情况下,创建的是org.springframework.boot.logging.logback.LogbackLoggingSystem类的对象,Logback是SpringBoot默认采用的日志系统。

 
  • 2

这里写图片描述

到这里,ApplicationStartedEvent事件的处理这样就结束了。

 
  • 2

创建并刷新ApplicationContext:

这里写图片描述

DefaultApplicationArguments:

 
  • 2

这里写图片描述

这里写图片描述

这里是把main函数的args参数当做一个PropertySource来解析,默认情况下,args的长度是0,所以这里创建的DefaultApplicationArguments也没有实际的内容。

 
  • 2

ConfigurableEnvironment:创建并配置ApplicationConext的Environment

这里写图片描述

首先要调用getOrCreateEnvironment方法获取一个Environment对象。

 
  • 2

这里写图片描述

在默认情况下,执行到此处时,environment成员变量为null,而webEnvironment成员变量的值为true,所以会创建一个StandardServletEnvironment对象并返回。

之后会调用ConfigurableEnvironment类型的对象的configureEnvironment方法来配置上一步获取到的Environment对象。

 
  • 4

这里写图片描述

configureEnvironment方法先是调用configurePropertySources来配置properties,然后调用configureProfiles来配置profiles。

 
  • 2

这里写图片描述

这里,configurePropertySources首先查看SpringApplication对象的成员变量defaultProperties,如果该变量非null且内容非空,则将其加入到Environment的PropertySource列表的最后。

之后查看SpringApplication对象的成员变量addCommandLineProperties和main函数的参数args,如果设置了addCommandLineProperties=true,且args个数大于0,那么就构造一个由main函数的参数组成的PropertySource放到Environment的PropertySource列表的最前面(这就能保证,我们通过main函数的参数来做的配置是最优先的,可以覆盖其他配置)。

在默认情况下,由于没有配置defaultProperties且main函数的参数args个数为0,所以这个函数什么也不做。

调用configureProfiles来配置profiles:

 
  • 8

这里写图片描述

configureProfiles首先会读取Properties中key为spring.profiles.active的配置项,配置到Environment。

 
  • 2

这里写图片描述

再将SpringApplication对象的成员变量additionalProfiles加入到Environment的active profiles配置中。

默认情况下,配置文件里没有spring.profiles.active的配置项,而SpringApplication对象的成员变量additionalProfiles也是一个空的集合,所以这个函数没有配置任何active profile。

 
  • 4

调用SpringApplicationRunListeners类的对象listeners发布ApplicationEnvironmentPreparedEvent事件:

到这一步时,Environment就算是配置完成了。接下来调用SpringApplicationRunListeners类的对象listeners发布ApplicationEnvironmentPreparedEvent事件。

 
  • 2

这里写图片描述

这里写图片描述

等到发布完事件之后,我们就可以看看,加载的ApplicationListener对象都有哪些响应了这个事件,做了什么操作:

FileEncodingApplicationListener响应该事件:

 
  • 2

这里写图片描述

检查file.encoding配置是否与spring.mandatory_file_encoding一致
在默认情况下,因为没有spring.mandatory_file_encoding的配置,所以这个响应方法什么都不做。


AnsiOutputApplicationListener响应该事件:

 
  • 6

这里写图片描述

根据spring.output.ansi.enabled和spring.output.ansi.console-available对AnsiOutput类做相应配置。在默认情况下,因为没有做配置,所以这个响应方法什么都不做。


ConfigFileApplicationListener响应该事件:

 
  • 5

这里写图片描述

这里写图片描述

可以看到,ConfigFileApplicationListener从META-INF/spring.factories文件中读取EnvironmentPostProcessor配置,加载相应的EnvironmentPostProcessor类的对象,并调用其postProcessEnvironment方法。在我们的例子中,会加载CloudFoundryVcapEnvironmentPostProcessor和SpringApplicationJsonEnvironmentPostProcessor并执行,由于我们的例子中没有CloudFoundry和Json的配置,所以这个响应,不会加载任何的配置文件到Environment中来。

 
  • 2

这里写图片描述

这里写图片描述

DelegatingApplicationListener响应该事件:将配置文件中key为context.listener.classes的配置项,加载在成员变量multicaster中

这里写图片描述

这里写图片描述

将配置文件中key为context.listener.classes的配置项,加载在成员变量multicaster中,因为在默认情况下没有key为context.listener.classes的Property,所以不会加载任何listener到该监听器中。

 
  • 2

LoggingApplicationListener响应事件:对在ApplicationStarted时加载的LoggingSystem做一些初始化工作

这里写图片描述

这里写图片描述

这里写图片描述

默认情况下,是对加载的LogbackLoggingSystem做一些初始化工作。

 
  • 2

打印Banner

这里写图片描述

这里写图片描述

printBanner方法中,首先会调用selectBanner方法得到一个banner对象,然后判断bannerMode的类型,如果是Banner.Mode.LOG,那么将banner对象转换为字符串,打印一条info日志,否则的话,调用banner对象的printbanner方法,将banner打印到标准输出System.out。

默认情况下,bannerMode是Banner.Mode.Console,而且也不曾提供过banner.txt这样的资源文件。所以selectBanner方法中得到到便是默认的banner对象,即SpringBootBanner类的对象:

 
  • 4

这里写图片描述

创建ApplicationContext:

这里写图片描述

SpringApplication中调用createApplicationContext获取创建ApplicationContext(IOC容器),可以看到,当检测到本次程序是一个web应用程序(成员变量webEnvironment为true)的时候,就加载类
DEFAULT_WEB_CONTEXT_CLASS,否则的话加载DEFAULT_CONTEXT_CLASS。我们的例子是一个web应用程序,所以会加载DEFAULT_WEB_CONTEXT_CLASS,也就是org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext。
AnnotationConfigEmbeddedWebApplicationContext类的作用(功能):

 
  • 4

这里写图片描述

可以看到我们加载的这个AnnotationConfigEmbeddedWebApplicationContext类,从名字就可以看出来,首先是一个WebApplicationContext实现了WebApplicationContext接口,然后是一个EmbeddedWebApplicationContext,这意味着它会自动创建并初始化一个EmbeddedServletContainer,同时还支持AnnotationConfig,会将使用注解标注的bean注册到ApplicationContext中。

总结起来就是:指定了容器的类名,最后通过Spring的工具类初始化容器类bean (BeanUtils.instantiate(contextClass))

 
  • 4

这里写图片描述

通过调用Class对象的newInstance()方法来实例化对象,这等同于直接调用类的空的构造方法,所以我们来看AnnotationConfigEmbeddedWebApplicationContext类的构造方法:

 
  • 2

这里写图片描述

构造方法中初始化了两个成员变量,类型分别为AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner用以加载使用注解的bean定义。
这样ApplicationContext对象就创建出来了,在createAndRefreshContext方法中创建了ApplicationContext对象之后会紧接着调用其setEnvironment将我们之前准备好的Environment对象赋值进去。之后分别调用postProcessApplicationContext和applyInitializers做一些处理和初始化的操作。

 
  • 3

这里写图片描述

如果成员变量beanNameGenerator不为Null,那么为ApplicationContext对象注册beanNameGenerator bean。如果成员变量resourceLoader不为null,则为ApplicationContext对象设置ResourceLoader。默认情况下,这两个成员变量都为Null,所以什么都不做。

 
  • 2

这里写图片描述

这里写图片描述

最后刷新上下文:

这里写图片描述

这里调用的是AbstractApplicationContext的refresh()方法刷新上下文。
1、this.prepareRefresh();
准备启动spring容器,设置容器的启动日期和活动标志

2、ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
主要是创建beanFactory,同时加载配置文件.xml中的beanDefinition  
通过String[] configLocations = getConfigLocations()获取资源路径,然后加载beanDefinition  

3、this.prepareBeanFactory(beanFactory);
给beanFactory注册一些标准组件,如ClassLoader,StandardEnvironment,BeanProcess  

4、this.postProcessBeanFactory(beanFactory);
提供给子类实现一些postProcess的注册,如AbstractRefreshableWebApplicationContext注册一些Servlet相关的postProcess,真对web进行生命周期管理的Scope,通过registerResolvableDependency()方法注册指定ServletRequest,HttpSession,WebRequest对象的工厂方法。

5、this.invokeBeanFactoryPostProcessors(beanFactory);
调用所有BeanFactoryProcessor的postProcessBeanFactory()方法  

6、this.registerBeanPostProcessors(beanFactory);
注册BeanPostProcessor,BeanPostProcessor作用是用于拦截Bean的创建  

7、this.initMessageSource();
初始化消息Bean  

8、this.initApplicationEventMulticaster();
初始化上下文的事件多播组建,ApplicationEvent触发时由multicaster通知给ApplicationListener  

9、this.onRefresh();
ApplicationContext初始化一些特殊的bean 

10、this.registerListeners();
注册事件监听器,事件监听Bean统一注册到multicaster里头,ApplicationEvent事件触发后会由multicaster广播  

11、this.finishBeanFactoryInitialization(beanFactory);
非延迟加载的单例Bean实例化

12、this.finishRefresh();
结束刷新

 
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

结束刷新容器之后执行的afterRefresh()方法:

这里写图片描述

这里写图片描述

实际应用中,我们会有在项目服务启动的时候就去加载一些数据或做一些事情这样的需求。比如读取配置文件,数据库连接之类的。SpringBoot给我们提供了两个接口来帮助我们实现这种需求。这两个接口分别为CommandLineRunner和ApplicationRunner。他们的执行时机为容器启动完成的时候。
这两个接口中有一个run方法,我们只需要实现这个方法即可。这两个接口的不同之处在于:ApplicationRunner中run方法的参数为ApplicationArguments,而CommandLineRunner接口中run方法的参数为String数组。

 
  • 3

结束监听器:

这里写图片描述

这里写图片描述

这里写图片描述

从上述代码中可以看出,finished()方法是通过发布**结束监听**这个事件,当实现onApplication(相应事件)的监听类监听到这个事件时,就会结束相应的监听。

 
  • 2

结束计时:

stopWatch.stop();

开始打印Log信息:

这里写图片描述

找到你的入口函数(xxApplication.class),开始打印Log信息。



原文链接:http://blog.csdn.net/zxzzxzzxz123/article/details/69941910


原文地址:https://blog.csdn.net/guo13313

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 目录 连接 连接池产生原因 连接池实现原理 小结 TEMPERANCE:Eat not to dullness;drink not to elevation.节制
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 一个优秀的工程师和一个普通的工程师的区别,不是满天飞的架构图,他的功底体现在所写的每一行代码上。-- 毕玄 1. 命名风格 【书摘】类名用 UpperCamelC
今天犯了个错:“接口变动,伤筋动骨,除非你确定只有你一个人在用”。哪怕只是throw了一个新的Exception。哈哈,这是我犯的错误。一、接口和抽象类类,即一个对象。先抽象类,就是抽象出类的基础部分,即抽象基类(抽象类)。官方定义让人费解,但是记忆方法是也不错的 —包含抽象方法的类叫做抽象类。接口
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:BYSocketFaceBook:BYSocketTwitter :BYSocket一、引子文件,作为常见的数据源。关于操作文件的字节流就是 —FileInputStream&amp;FileOutputStream。
作者:泥沙砖瓦浆木匠网站:http://blog.csdn.net/jeffli1993个人签名:打算起手不凡写出鸿篇巨作的人,往往坚持不了完成第一章节。交流QQ群:【编程之美 365234583】http://qm.qq.com/cgi-bin/qm/qr?k=FhFAoaWwjP29_Aonqz
本文目录 线程与多线程 线程的运行与创建 线程的状态 1 线程与多线程 线程是什么? 线程(Thread)是一个对象(Object)。用来干什么?Java 线程(也称 JVM 线程)是 Java 进程内允许多个同时进行的任务。该进程内并发的任务成为线程(Thread),一个进程里至少一个线程。 Ja
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:BYSocketFaceBook:BYSocketTwitter :BYSocket在面向对象编程中,编程人员应该在意“资源”。比如?1String hello = &quot;hello&quot;; 在代码中,我们
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 这是泥瓦匠的第103篇原创 《程序兵法:Java String 源码的排序算法(一)》 文章工程:* JDK 1.8* 工程名:algorithm-core-le
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 目录 一、父子类变量名相同会咋样? 有个小故事,今天群里面有个人问下面如图输出什么? 我回答:60。但这是错的,答案结果是 40 。我知错能改,然后说了下父子类变
作者:泥瓦匠 出处:https://www.bysocket.com/2021-10-26/mac-create-files-from-the-root-directory.html Mac 操作系统挺适合开发者进行写代码,最近碰到了一个问题,问题是如何在 macOS 根目录创建文件夹。不同的 ma
作者:李强强上一篇,泥瓦匠基础地讲了下Java I/O : Bit Operation 位运算。这一讲,泥瓦匠带你走进Java中的进制详解。一、引子在Java世界里,99%的工作都是处理这高层。那么二进制,字节码这些会在哪里用到呢?自问自答:在跨平台的时候,就凸显神功了。比如说文件读写,数据通信,还
1 线程中断 1.1 什么是线程中断? 线程中断是线程的标志位属性。而不是真正终止线程,和线程的状态无关。线程中断过程表示一个运行中的线程,通过其他线程调用了该线程的 方法,使得该线程中断标志位属性改变。 深入思考下,线程中断不是去中断了线程,恰恰是用来通知该线程应该被中断了。具体是一个标志位属性,
Writer:BYSocket(泥沙砖瓦浆木匠)微博:BYSocket豆瓣:BYSocketReprint it anywhere u want需求 项目在设计表的时候,要处理并发多的一些数据,类似订单号不能重复,要保持唯一。原本以为来个时间戳,精确到毫秒应该不错了。后来觉得是错了,测试环境下很多一
纯技术交流群 每日推荐 - 技术干货推送 跟着泥瓦匠,一起问答交流 扫一扫,我邀请你入群 纯技术交流群 每日推荐 - 技术干货推送 跟着泥瓦匠,一起问答交流 扫一扫,我邀请你入群 加微信:bysocket01
Writer:BYSocket(泥沙砖瓦浆木匠)微博:BYSocket豆瓣:BYSocketReprint it anywhere u want.文章Points:1、介绍RESTful架构风格2、Spring配置CXF3、三层初设计,实现WebService接口层4、撰写HTTPClient 客户
Writer :BYSocket(泥沙砖瓦浆木匠)什么是回调?今天傻傻地截了张图问了下,然后被陈大牛回答道“就一个回调…”。此时千万个草泥马飞奔而过(逃哈哈,看着源码,享受着这种回调在代码上的作用,真是美哉。不妨总结总结。一、什么是回调回调,回调。要先有调用,才有调用者和被调用者之间的回调。所以在百
Writer :BYSocket(泥沙砖瓦浆木匠)一、什么大小端?大小端在计算机业界,Endian表示数据在存储器中的存放顺序。百度百科如下叙述之:大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加
What is a programming language? Before introducing compilation and decompilation, let&#39;s briefly introduce the Programming Language. Programming la
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:BYSocketFaceBook:BYSocketTwitter :BYSocket泥瓦匠喜欢Java,文章总是扯扯Java。 I/O 基础,就是二进制,也就是Bit。一、Bit与二进制什么是Bit(位)呢?位是CPU
Writer:BYSocket(泥沙砖瓦浆木匠)微博:BYSocket豆瓣:BYSocket一、前言 泥瓦匠最近被项目搞的天昏地暗。发现有些要给自己一些目标,关于技术的目标:专注很重要。专注Java 基础 + H5(学习) 其他操作系统,算法,数据结构当成课外书博览。有时候,就是那样你越是专注方面越