Spring底层工厂创建对象流程
在磁盘中有很多的Class文件,运行时要把磁盘中的文件读到JVM的内存中(需要用到线程和I/O),系统底层会创建一个BeanDefinition对象用于存储bean的配置信息,多个class文件就会创建多个BeanDefinition对象,这些对象存放在一个Map集合中(包,注解....),通过工厂创建Bean Instance(Bean的实例)存储在Map中,其中String中存储的是名字,可以在@Component注解中指定名字,若是不指定名字则类名首字母小写为默认名字,在构建Bean对象的时候,先查找Bean的配置信息,在找不到的时候就会报错
SpringBoot项目加载流程
任何一个项目都有一个启动入口,在springboot中的启动类需要有@SpringBootApplication 注解进行描述,并且在列中会定义一个main方法,main方法在运行时会读取配置文件,并加载指定资源,然后进行初始化操作
描述了DefaultCacheTests类与DefaultCache类的关系,这两个类通过指定注解(@SpringBootTest,@Component)进行了描述,其意图是告诉spring框架这个两个类的实例的创建由Spring负责,并且由Spring框架基于@Autowired注解的描述完成DefaultCacheTests实例中有关DefaultCache类型的值的注入(DI)。
Spring Boot项目中配置文件来源
a)SpringBoot官方定义(一般为一些基础配置)例如 spring.factories(在SpringBoot自动配置依赖中)
b) 第三方定义(例如日志系统-log4j.xml...)
c) 我们自己定义(application.properties)
SpringBoot项目中的资源加载(资源可以理解为我们的class文件)
a)JDK类文件
b)Spring类文件
c)自己定义的类文件
JVM参数:-XX:+TraceClassLoading(跟踪类加载)
JVM参数录入路径:类名右键Run As选择Run Configurations
1.选择Arguments
2.录入在main方法中的形参(String[] arg)这里面写的就是arg中的值
3.将需要执行的JVM参数放入三种,点击Run执行
任意项目整体执行顺序打开JDK包-->加载Object类-->加载Serializable(序列化)-->加载Comparable(比较类)-->加载CharSequence(字符序列)-->加载String(字符串类)
PS:当执行后没有显示出第一条数据时,可以调整显示的字符个数如图所示调整控制台输出字符个数:
SpringBoot中的项目资源初始化
a)构建实例对象
b)基于对象存储数据(例如配置信息,默认值)
对象的两种用法,一种是封装数据,一种是业务流程(执行业务靠方法)
Spring Boot项目执行
SpringBoot项目大体分为三个包
a)启动包,在启动包中添加代码逻辑,而且执行类一定要在启动包下或子包下
b)配置包,将所有的配置信息文件写在配置包中
c)单元测试包,在单元测试包中写入测试代码,测试类一定要写在单元测试包下或子包下
SpringBoot项目执行中的注解
@SpringBootApplication
任何一个项目都有一个启动入口,在springboot中的启动类需要有@SpringBootApplication 注解进行描述,并且在列中会定义一个main方法,main方法在运行时会读取配置文件,并加载指定资源,然后进行初始化操作
@Component
将类使用spring框架中指定注解进行描述,例如@Component注解起的作用就是做标记
@SpringBootTest
@SpringBootTest注解是SpringBoot工程中的单元测试类需要使用此注解进行描述
@Test
单元测试类注解,与普通的测试类注解使用方法相同,要注意导包,SpringBoot项目中导入的@Test包为org.junit.jupiter.api.Test
测试方法不可以用private修饰也不可以有返回值以及参数
is a
类实现了一个接口或是继承了一个类是is a
has a
在某一类中有一个属性是has a
use a
在某一个类中某个方法中使用了某个类是use a
SpringBoot业务常用注解
@Lazy
注解修饰的类就是告诉spring容器这个类在用不到的时候先不要创建可以在后面添加值一般默认为true(@Lazy(true),@Lazy(value=true))true/false就是设置注解是否延时加载
@Scope
@Scope("singleton")
没有写但是默认就是这个注解,默认为单例作用域,这个类的实例在一个Spring容器中只能有一份,因为只有一份,所以在后来一定要考虑线程安全
@Scope("prototype")
每次从Spring容器中获取对象都会创建一个新的实例,不会存储在Spring的Bean池中
@PostConstruct
注解描述的方法会在**对象构建以后执行!!!**先执行对象的构造方法后再执行注解修饰的方法,用于执行一些初始化操作,比如在构建池的时候初始化池的参数、大小、连接超时时间......
@PreDestroy
注解描述的方法会在单例对象销毁之前执行,Spring容器(Bean池)在销毁之前会先将容器中的对象进行移除在移除对象时,假如对象中定义了生命周期销毁方法,此时还会调用对象的生命周期销毁方法(在这样的方法中可以做一席而资源释放操作)
常见问题
在出现错误问题时首先要先找Cased by(原因)
错误概述:
在spring容器中没有Bean类型的定义。
出现这类问题的可能:
1、启动类的包没有放在指定的位置下,没有在启动包或启动包的子包下
2、注解错误
假如将此类交给Spring管理,请问spring何时创建此对象?你怎么知道的?
一般来说,在系统启动的同时就创建对象,通过在类中准备构造函数,在运行项目的同时会执行构造方法中的代码
假如一个对象创建以后,存储到内存,长时间不用会有什么影响?
会影响电脑速度,抢占内存
你知道Spring中Bean对象的延迟加载特性吗?(了解)
按需加载,对于占用内存较多的对象,尽量使用在有需要的时候在加载
对象创建以后,应用结束要销毁对象吗
Spring容器只能销毁或是移除单例对象,多例对象不会存储在Spring的Bean池中,多以不会销毁或移除
Spring框架管理Bean对象有什么优势吗?
首先Spring为你的Bean赋予了延迟加载、作用域、生命周期方法,基于这些特性可以更加科学的使用对象,