SpringBoot 我的项目创立

创立Module

基于IDEA创立我的项目Module,模块名为04-springboot-start,组id和包名为com.cy,如图所示:

填写module信息,如图所示:

抉择我的项目module版本,临时不须要本人手动增加任何依赖,如图所示:

填写Module名称,实现module创立,如图所示

我的项目构造剖析

我的项目Module创立好当前,其代码构造剖析,如图所示:

SpringBoot 我的项目启动剖析

启动入口

SpringBoot 工程中由SpringBootApplication注解形容的类为启动入口类,例如:

package com.cy;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class Application {//Application.class  public static void main(String[] args) {//Main Thread    SpringApplication.run(Application.class, args);  }}

启动过程概要剖析

SpringBoot工程启动时其繁难初始化过程,如图所示:

在启动过程中底层做了哪些事件,大抵形容如下:
1)基于配置加载类(通过ClassLoader将指定地位的类读到内存->底层通过线程调用IO从磁盘读取到内存)。
2)对类进行剖析(创立字节码对象-Class类型,通过反射获取器配置信息)。
3)对于指定配置(例如由spring特定注解形容)的对象存储其配置信息(借助BeanDefinition对象存储)。
4)基于BeanDefinition对象中class的配置构建类的实例(Bean对象),从进行bean对象的治理。

SpringBoot 疾速入门剖析

业务形容

在我的项目Module中定义一个类,类名为DefaultCache,而后将此类对象交给Spring创立并治理。最初通过单元测试对类的实例进行剖析。

API设计剖析

基于业务形容,进行API及关系设计,如图所示:

代码编写及运行

基于业务及API设计,进行代码编写,其过程如下:

第一步:定义DefaultCache类

package com.cy.pj.common.cache;import org.springframework.stereotype.Component;/** * @Component 注解形容的类,示意此类交给Spring框架治理。 */@Componentpublic class DefaultCache {}

第二步:定义DefaultCacheTests单元测试类

package com.cy.pj.common.cache;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;public class DefaultCacheTests {    /** * @Autowired 注解形容的属性由spring框架依照肯定规定为其注入值(赋值) * 赋值过程是怎么的? *  1)依赖查找?(请问查找规定是什么?) *  2)依赖注入?(须要借助什么技术?) */ @Autowired private DefaultCache defaultCache;    @Test void testDefaultCache(){        System.out.println(defaultCache.toString());        //FAQ? defaultCache变量援用的对象是由谁创立的,存储到了哪里?bean pool }}

第三步:运行单元测试类进行利用剖析
启动运行单元测试办法,检测其输入后果,基于后果剖析:
1)SpringBoot我的项目中Bean对象的构建。
2)SpringBoot我的项目中Bean对象的获取。

运行过程中的BUG剖析

  • Bean类型找不到,如图所示:

  • 空指针异样(NullPointerExcetpion-NPE),如图所示:

SpringBoot 我的项目中的对象个性剖析

筹备工作

第一步:创立我的项目Module,例如名字为05-springboot-features,如图所示:

第二步:增加业务类ObjectPool,代码如下:

package com.cy.pj.common.pool;@Componentpublic class ObjectPool{//假如此对象为一个对象池    public ObjectPool(){//假如运行我的项目启动类,此构造方法执行了,阐明此类对象构建了。      Systemd.out.println("ObjectPool()")    }}

思考:个别池对象有什么特点?
1)在JVM内存会开拓一块绝对比拟大的空间。
2)在这块空间中存储一些对象(思考基于什么存储构造进行存储-数组,链表,散列表)。
3)基于“享元模式”设计思维,实现内存中对象的可重用性。

第三步:定义单元测试,代码如下:

package com.cy.pj.pool;import com.cy.pj.common.pool.ObjectPool;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;@SpringBootTestpublic class ObjectPoolTests {    @Autowired    private ObjectPool objectPool01;    @Autowired    private ObjectPool objectPool02;    @Test    void testObjectPool01(){       System.out.println(objectPool01==objectPool02);    }}

提早加载

当初思考一个问题,对于ObjectPool这个类,如果我的项目启动当前,临时不会用到这个池对象,是否有必要对其进行创立(默认是会创立的)?咱们晓得没必要,因为占用内存。那如何在启动时不创立此类对象呢?借助Spring框架提供的提早加载个性进行实现。例如,咱们能够在须要提早加载的类上应用@Lazy注解进行形容,代码如下:

package com.cy.pj.common.pool;@Lazy@Componentpublic class ObjectPool{//假如此对象为一个对象池    public ObjectPool(){//假如运行我的项目启动类,此构造方法执行了,阐明此类对象构建了。      Systemd.out.println("ObjectPool()")    }}

此时,咱们再去运行运行启动类,检测ObjectPool对象是否创立了,如果没有创立,阐明提早加载失效了。此时,咱们总结一下,什么对象适宜应用提早加载个性呢?大对象,稀少用(我的项目启动当前,临时用不到)的对象。
留神:提早加载并不是提早对类进行加载,而是在启动时,临时不创立类的实例。如果想看一下内存中的类是否被加载了,能够通过JVM参数进行检测,参数为-XX:+TraceClassLoading。

对象作用域剖析

在理论的我的项目中内存中的对象有一些可能要重复利用很屡次,有一些可能用完当前再也不必了或者说利用次数很少了。对于常常要重复使用的对象我可思考存储到池中(例如交给spring框架进行治理),利用次数很少的对象那就没必要放到池中了,用完当前让它本人销毁就能够了。在Spring我的项目工程中为了对这样的对象进行设计和治理,提供了作用域个性的反对,具体利用:

package com.cy.pj.common.pool;@Scope("singleton")@Lazy@Componentpublic class ObjectPool{//假如此对象为一个对象池    public ObjectPool(){//假如运行我的项目启动类,此构造方法执行了,阐明此类对象构建了。      Systemd.out.println("ObjectPool()")    }}

其中,在下面的代码中,咱们应用了@Scope注解对类进行形容,用于指定类的实例作用域。不写@Scope默认就是单例(singleton)作用域,这个作用域会配合提早加载(@Lazy)个性应用,示意此类的实例在须要时能够创立一份并且将其存储到spring的容器中(Bean池),须要的时候从池中取,以实现对象的可重用。如果一些对象利用次数非常少,能够思考不放入池中,进而应用@Scope("prototype")作用域对类进行形容,让此类的对象何时须要何时创立,用完当前,当此对象不可达了,则能够间接被GC零碎销毁。

对象生命周期办法

程序中的每个对象都有生命周期,对象创立,初始化,利用,销毁的这个过程称之为对象的生命周期。在对象创立当前要初始化,利用实现当前要销毁时执行的一些办法,咱们能够称之为生命周期办法。但不见得每个对象都会定义生命周期办法。在理论我的项目中往往一些池对象通常会定义这样的一些生命周期办法(例如连接池)。那这样的办法在spring工程中如何进行标识呢?通常要借助@PostConstruct和@PreDestroy注解对特定办法进行形容,例如:

package com.cy.pj.common.pool;@Scope("singleton")@Lazy@Componentpublic class ObjectPool{//假如此对象为一个对象池    public ObjectPool(){      Systemd.out.println("ObjectPool()")    }    @PostConstruct    public void init(){       System.out.println("init()");    }    @PreDestroy    public void destory(){     System.out.println("destory()");    }}

其中:
1)@PostConstruct 注解形容的办法为生命周期初始化办法,在对象构建当前执行.
2)@PreDestroy 注解形容的办法为生命周期销毁办法,此办法所在的对象,如果存储到了spring容器,那这个对象在从spring容器移除之前会先执行这个生命周期销毁办法(prototype作用域对象不执行此办法).

SpringBoot 我的项目中的依赖注入过程剖析

在SpringBoot工程中,如果类与类之间存在着肯定的依赖关系,Spring是如何进行依赖注入的呢,当初咱们就通过一个案例做一个剖析。

筹备工作

第一步:创立一个我的项目module,如图所示:

第二步:启动运行我的项目,检测是否能胜利启动

案例设计及剖析

为了更好了解spring框架的底层注入机制,当初进行案例API设计,如图所示:

在这个案例中单元测试类CacheTests中定义一个Cache接口类型的属性,而后由Spring框架实现对cache类型属性值的注入。

代码编写及测试剖析

第一步:定义Cache接口,代码如下:

package com.cy.pj.common.cache;public interface Cache { }

第二步:定义Cache接口实现类SoftCache,代码如下:

package com.cy.pj.common.cache; @Componentpublic class SoftCache implements Cache{}

第三步:定义Cache接口实现类WeakCache,代码如下:

package com.cy.pj.common.cache; @Componentpublic class WeakCache implements Cache{}

第四步:定义CacheTests单元测试类,代码如下:

package com.cy.pj.common.cache;import org.junit.jupiter.api.Test;@SpringBootTest    public class CacheTests {    @Autowired    @Qualifier("softCache")    private Cache cache;        @Test    public void testCache() {        System.out.println(cache);    }} 

其中,@Autowired由spring框架定义,用于形容类中属性或相干办法(例如构造方法)。Spring框架在我的项目运行时如果发现由他治理的Bean对象中有应用@Autowired注解形容的属性或办法,能够依照指定规定为属性赋值(DI)。其根本规定是:首先要检测容器中是否有与属性或办法参数类型相匹配的对象,如果有并且只有一个则间接注入。其次,如果检测到有多个,还会依照@Autowired形容的属性或办法参数名查找是否有名字匹配的对象,有则间接注入,没有则抛出异样。最初,如果咱们有明确要求,必须要注入类型为指定类型,名字为指定名字的对象还能够应用@Qualifier注解对其属性或参数进行形容(此注解必须配合@Autowired注解应用)。

第五步:运行CacheTests检测输入后果,基于后果了解其注入规定。

编写及测试过程中的BUG剖析

  • 依赖注入异样,如图所示:

总结(Summary)

本大节为springboot技术入门章节,次要讲述了SpringBoot工程下,spring中bean对象的编写,个性以及依赖注入的规定,心愿通过这一大节的解说,同学们可能了解咱们为什么要将对象交给spring治理,spring治理对象有什么劣势,咱们在springboot工程中应该如何配置这些对象。