鞋圖相冊網(wǎng)站怎么做app拉新平臺哪個好傭金高
SpringBoot底層原理
一 配置優(yōu)先級
1.配置方式
Springboot中支持三種配置方式,分別為:
- application.properties
- application.yml
- application.yaml
2.配置優(yōu)先級
當存在多份配置文件時,配置文件會按照它們的優(yōu)先級生效。
優(yōu)先級從高到底分別為:application.peoperties>
application.yml>
application.yaml
目前 application.yml 是最主流的方式
3.其他配置方式
Springboot除了以上常見的三種配置方式之外,還支持Java系統(tǒng)屬性
配置和命令行參數(shù)
配置。
1.Java系統(tǒng)屬性配置示例
# 在 java 命令后使用 —D 命令,然后書寫需要配置的屬性即可
# 示例中配置了項目的運行端口為8081,即server.port=8081
java -Dserver.port=8081 -jar [packageName].jar
2.命令行參數(shù)配置示例
# 在jar包名稱之后,使用雙橫杠(--),后面緊跟配置的參數(shù)即可
java -jar [packageName].jar --server.port=8082
二 Bean管理
1.獲取bean對象
默認情況下,Springboot項目在啟動時會自動創(chuàng)建bean,并且將這些bean都存放在IOC容器中。
如果想手動獲取這些bean,則可以通過以下幾種示例。
首先需要注入ApplicationContext對象。
在 Spring框架
中,ApplicationContext是一個接口,代表了Spring容器
,它負責管理Spring應用程序中所有的bean,同時提供了一些方法來獲取Bean,注冊Bean,是整個Spring應用的核心。
默認情況下,一個Bean的名稱是它的類名名稱,然后將首字母小寫。
例如 DeptController,它在IOC容器中的默認名稱為 deptController
@Autowired
private ApplicationContext applicationContext;
@Test
void test1(){//1.根據(jù)bean的名稱來獲取bean對象EmpServiceImpl empServiceImpl1= (EmpServiceImpl) applicationContext.getBean("empServiceImpl");System.out.println(empServiceImpl1);//2.根據(jù)bean的類型來獲取bean對象EmpServiceImpl empServiceImpl2= applicationContext.getBean(EmpServiceImpl.class);System.out.println(empServiceImpl2);//3.根據(jù)bean的類型和名稱來獲取bean對象// 以下方法和示例,在bean的默認名稱被修改且有多個同類型的bean時,尤為有用。EmpServiceImpl empServiceImpl3= applicationContext.getBean("empServiceImpl",EmpServiceImpl.class);System.out.println(empServiceImpl3);
}
運行以上示例,可以看出,bean在IOC容器中,默認是單例
存在的。
如果想要實現(xiàn)每次使用時都是一個新的bean,則需要通過bean的
作用域
來進行配置。
2.bean的作用域
在Spring中,bean支持五種作用域,后三種在web環(huán)境下才能生效。
默認情況下,Bean對象在項目啟動時就會默認實例化。如果不希望在項目啟動時就初始化,可以使用@Lazy
注解,讓Bean對象延遲初始化,直到第一次使用該Bean時才會進行初始化。
@Service
@Lazy
public class EmpServiceImpl extends ServiceImpl<EmpMapper, Emp> implements EmpService{//code...
}
設置Bean的作用域,則需要通過@Scope
注解來實現(xiàn)。
以下示例中,我們將Bean的作用域設置為 prototype
,即每次使用該Bean時都會創(chuàng)建新對象。
@Service
@Scope("prototype")
public class EmpServiceImpl extends ServiceImpl<EmpMapper, Emp> implements EmpService{//code...
}
現(xiàn)在再次運行前邊獲取Bean對象的代碼示例,可以發(fā)現(xiàn),三次獲取到的Bean對象,已經(jīng)不是同一個。
3.聲明第三方bean
如果要申明的Bean來自第三方,是無法通過@Component及衍生注解來申明的,這個時候就需要使用@Bean
注解。
以 SAXReader 類為例,創(chuàng)建一個返回值為SAXReader對象
的方法,方法名稱就是以后被ICO管理的Bean對象名稱。
//將方法的返回值交給IOC容器管理,稱為IOC容器的Bean對象
@Bean
public SAXReader saxReader(){return new SAXReader();
}
在以后需要用到 SAXReader 對象
的時候,直接注入即可,不用去實例化。
@Autowired
private SAXReader saxReader;
@Test
void test2() throws DocumentException {Document document = saxReader.read("xxx");
}
注意:一般情況下,我們通常會將所有需要申明的第三方bean對象統(tǒng)一放在一個配置類中,這樣更加方便維護。
@Configuration
public class BeanAutoConfig {// 可以通過@Bean注解的 name /value 屬性來定義bean的名稱// 默認情況下,bean的名稱就是方法名@Beanpublic RestTemplate restTemplate(){return new RestTemplate();}}
在聲明第三方bean對象時,如果需要進行依賴注入,則只需要指定方法形參即可。Spring會根據(jù)類型進行自動裝配。
// EmpServiceImpl對象是要注入的bean對象
@Bean
public RestTemplate restTemplate(EmpServiceImpl empServiceImpl){empServiceImpl.[xxx];return new RestTemplate();
}
三 Springboot原理
1.Springboot起步依賴
Springboot整合了以前web開發(fā)需要用的一些依賴項,目前使用Springboot開發(fā)web項目,只需要引入 spring-boot-start-web
依賴即可。
歸根結底,SPringboot起步依賴的原理就是maven的依賴傳遞
。
2.自動配置
當Springboot項目啟動后,Springboot中的一些配置類,bean對象就會自動存入到IOC容器中,不需要我們手動去申明。從而簡化了開發(fā),省去了繁瑣的配置。
3.管理第三方包中的Bean
1.配置實現(xiàn)方式1:@ComponentScan 組件掃描
在啟動類上使用 @ComponentScan
注解,重新配置包掃描路徑。@ComponentScan
的basePackages
參數(shù)支持數(shù)據(jù)格式,當有多個第三方包時,可使用數(shù)組形式申明。
@ComponentScan(basePackages = "xxx1")
或
@ComponentScan(basePackages = {"xxx1","xxx2"
})
注意:使用@ComponentScan
申明時,當前Springboot項目
中的包路徑也必須包含在內(nèi),否則當前項目中的bean將會被無法識別。
缺點:當項目較大時,引入大量的第三方依賴,此時啟動類將會顯得臃腫。
2.配置實現(xiàn)方式2:@Import 組件導入
使用@Import導入的類會被Spring加載到容器中??梢詫肫胀?#xff0c;配置類,以及 ImportSelector 接口的實現(xiàn)類,支持數(shù)組。
@Import({xx1.class,xx2.class})
實現(xiàn)ImportSelector 接口,這里最核心的就是 selectImports方法
,它返回了需要創(chuàng)建Bean對象的全部類。
public class MyImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {//此處的數(shù)組內(nèi)容為需要導入的Bean對象的全類名,有多少寫多少return new String[]{"springboot.demo.GoodStudent"};}
}
然后在啟動類上使用@Import
注解即可。
@Import({MyImportSelector.class})
單純使用 @Import
接口聲明第三方Bean,缺點很明顯。
3.配置實現(xiàn)方式3:第三方依賴提供注解
實際項目中,具體第三方依賴需要導入哪些Bean,只有第三方依賴自己知道。所以可以由第三方依賴提供注解,然后在項目中引入即可。
此類型注解一般均由 Enable
開頭,原理是在自定義注解中封裝 @Import
注解。
示例:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import({MybatisPlusConfig.class,CorsConfig.class,SpringWebConfig.class,BeanAutoConfig.class,RedisConfig.class
})
public @interface EnableShawnConfig {}
在第三方依賴包中定義一個EnableShawnConfig
注解,然后使用 @Import
將需要配置的Bean對象都引入進來。最后再在項目中使用該注解即可。
@EnableShawnConfig
@SpringBootApplication
public class ShawnServerSystemApplication {public static void main(String[] args) {SpringApplication.run(ShawnServerSystemApplication.class, args);}
}
4.自動配置原理分析
Springboot核心注解:@SpringBootApplication
@SpringBootApplication
下的重要注解:
@SpringBootConfiguration
:申明當前注解也是一個配置類,因為@SpringBootConfiguration
中也申明了@Configuration
注解。所以可以直接在啟動類中申明第三方的bean對象。@EnableAutoConfiguration
:Springboot自動配置的核心注解,它聲明了@Import(AutoConfigurationImportSelector.class)
,AutoConfigurationImportSelector
是ImportSelector
接口的實現(xiàn)類,實現(xiàn)了selectImports 方法
。selectImports 方法
返回了需要創(chuàng)建Bean對象的全部信息。@ComponentScan
:組件掃描,默認掃描當前引導類及其所在的子包。
自動配置最核心的注解就是@EnableAutoConfiguration
,由源碼可知,selectImports 方法
會讀取一個固定目錄下后綴名為.imports
的文件。
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {List<String> configurations = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).getCandidates();Assert.notEmpty(configurations,"No auto configuration classes found in "+ "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "+ "are using a custom packaging, make sure that file is correct.");return configurations;
}
springboot3.x中,META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中,配置了需要創(chuàng)建Bean對象的全類名
在Springboot2.x中,是通過兩個關鍵文件來讀取配置好的全類名的。
spring.factories
是早起Springboot版本中自動配置的文件,在后續(xù)版本中已經(jīng)逐漸不再使用。
5.@Conditinal注解
@Conditinal
注解的作用:按照一定的條件判斷,在滿足條件后才會注冊對應的Bean對象到IOC容器中
它可以作用在類
和方法
上。
@Conditinal
本身是一個父級注解,它衍生除了很多子級注解
@ConditionalOnClass
:判斷環(huán)境中是否存在字節(jié)碼文件,有則注冊bean對象到IOC容器@ConditionalOnMissingBean
:判斷環(huán)境中有沒有對應的Bean(根據(jù)類型和名稱),沒有則注冊Bean對象到IOC容器@ConditionalOnProperty
:判斷配置文件中是否有對應屬性和值,有則注冊bean對象到IOC容器