SpringBoot启动过程中底层做了哪些?
- 基于配置加载类,将类(启动类所蕴含的:JVM根底类库优先,spring外部类库...可通过栈追踪 -XX:TraceClassLoading 对JVM参数剖析)读到内存。
- 对具备注解、配置文件特定配置的对象进行存储配置信息(借助BeanDefinition存储)
- 基于BeanDefinition对象中的class的配置构建类的实例Bean对象,并进行Bean对象治理(有些可能存储到bean池中)。
业务形容
在我的项目Module中定义一个类,类名为DefaultCache,而后将此类对象交给Spring创立并治理。最初通过单元测试对类的实例进行剖析。
API设计剖析
基于业务形容,进行API及关系设计,如图所示:
基于业务及API设计,进行代码编写,其过程如下:
1:
package com.cy.pj.common.cache;
import org.springframework.stereotype.Component;
@Component
//用来形容由spring治理的个别(common)组件
public class DefaultCache {
}
2:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
//此注解形容的类为springboot工程中的单元测试类
public class DefaultCacheTests {
//has a
@Autowired
//此注解用于通知spring请按指定规定为此属性赋值
private DefaultCache defaultCache;
@Test
public void testDefaultCache(){
System.out.println("测试:");
System.out.println(defaultCache.toString());
}
}
SpringBoot 我的项目中的对象个性剖析
1:
package com.cy.pj.common.pool;
import org.springframework.stereotype.Component;
@Component
public class ObjectPool {
public ObjectPool(){ //通常利用构造方法来检测该类有没有创立
System.out.println("ObjectPool类创立了!");
}
}
2:
package com.cy.pj.common.pool;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class ObjectPoolTests {
@Autowired
private ObjectPool objectPool01;
@Autowired
private ObjectPool objectPool02;
@Test
void testObjectPool(){
System.out.println("测试:");
System.out.println(objectPool01==objectPool02);
/**
- 若为true,则表明为同一对象,即没有创立新对象
- 阐明了BeanPool中有且只有一个对象ObjectPool
*/
提早加载
当初思考一个问题,对于ObjectPool这个类,如果我的项目启动当前,临时不会用到这个池对象,是否有必要对其进行创立(默认是会创立的)?咱们晓得没必要,因为占用内存。那如何在启动时不创立此类对象呢?借助Spring框架提供的提早加载个性进行实现。例如,咱们能够在须要提早加载的类上应用@Lazy注解进行形容,代码如下:
package com.cy.pj.common.pool;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@Lazy
@Component
public class ObjectPool {
public ObjectPool(){ //通常利用构造方法来检测该类有没有创立
System.out.println("ObjectPool类创立了!");
}
}
对象作用域剖析
在理论的我的项目中内存中的对象有一些可能要重复利用很屡次,有一些可能用完当前再也不必了或者说利用次数很少了。对于常常要重复使用的对象我可思考存储到池中(例如交给spring框架进行治理),利用次数很少的对象那就没必要放到池中了,用完当前让它本人销毁就能够了。在Spring我的项目工程中为了对这样的对象进行设计和治理,提供了作用域个性的反对,具体利用:
package com.cy.pj.common.pool;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Scope("singleton")
@Lazy
@Component
public class ObjectPool {
public ObjectPool(){ //通常利用构造方法来检测该类有没有创立
System.out.println("ObjectPool类创立了!");
}
}
其中,在下面的代码中,咱们应用了@Scope注解对类进行形容,用于指定类的实例作用域。不写@Scope默认就是单例(singleton)作用域,这个作用域会配合提早加载(@Lazy)个性应用,示意此类的实例在须要时能够创立一份并且将其存储到spring的容器中(Bean池),须要的时候从池中取,以实现对象的可重用。如果一些对象利用次数非常少,能够思考不放入池中,进而应用@Scope("prototype")作用域对类进行形容,让此类的对象何时须要何时创立,用完当前,当此对象不可达了, 没有援用对象时,则能够间接被GC零碎销毁。
对象生命周期办法
程序中的每个对象都有生命周期,对象创立,初始化,利用,销毁的这个过程称之为对象的生命周期。在对象创立当前要初始化,利用实现当前要销毁时执行的一些办法,咱们能够称之为生命周期办法。但不见得每个对象都会定义生命周期办法。在理论我的项目中往往一些池对象通常会定义这样的一些生命周期办法(例如连接池)。那这样的办法在spring工程中如何进行标识呢?通常要借助@PostConstruct和@PreDestroy注解对特定办法进行形容,例如:
package com.cy.pj.common.pool;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Scope("singleton")
@Lazy
@Component
public class ObjectPool {
public ObjectPool(){ //通常利用构造方法来检测该类有没有创立
System.out.println("ObjectPool类创立了!");
}
@PostConstruct
//该注解形容的办法为生命周期初始化办法,在构建办法前执行
public void init(){
System.out.println("init()");
}
@PreDestroy
/**
- 该注解形容的办法为生命周期销毁办法,此办法所在的对象
- 若存储到spring容器中,则在销毁容器前,先执行该办法
- prototype作用域对象不执行该办法
*/
public void destroy(){
System.out.println("destroy()");
}
}
SpringBoot 我的项目中的依赖注入过程剖析
在SpringBoot工程中,如果类与类之间存在着肯定的依赖关系,Spring是如何进行依赖注入的呢,当初咱们就通过一个案例做一个剖析。
案例设计及剖析
为了更好了解spring框架的底层注入机制,当初进行案例API设计,如图所示:
代码编写及测试剖析
第一步:定义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;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;@SpringBootTestpublic class CacheTests { @Autowired //@Qualifier("") /** * 此处必须指定实现类的类型 * 即实现Cache有两个类,SoftCache和WeakCache * 但不指定类型时,底层不晓得找哪一个,就会报错 * 能够通过@Qualifier("softCache")来指定类型 * 也可通过 Cache softCache让其比拟参数自行查找 * 该参数是底层创立并 命名的,默认类名(首字母小写) */ private Cache softCache; @Test void testCache(){ System.out.println("测试:"); System.out.println(softCache); }}
其中,@Autowired由spring框架定义,用于形容类中属性或相干办法(例如构造方法)。Spring框架在我的项目运行时如果发现由他治理的Bean对象中有应用@Autowired注解形容的属性或办法,能够依照指定规定为属性赋值(DI)。其根本规定是:首先要检测容器中是否有与属性或办法参数类型相匹配的对象,如果有并且只有一个则间接注入。其次,如果检测到有多个,还会依照@Autowired形容的属性或办法参数名查找是否有名字匹配的对象,有则间接注入,没有则抛出异样。最初,如果咱们有明确要求,必须要注入类型为指定类型,名字为指定名字的对象还能够应用@Qualifier注解对其属性或参数进行形容(此注解必须配合@Autowired注解应用)。
第五步:运行CacheTests检测输入后果,基于后果了解其注入规定。