spring cloud每次修改必须重新打包_Java面试系列spring相关
Spring中的Bean是線程安全的嗎?
Spring 中的 bean 默認都是單例的,所有線程都共享一個單例實例Bean,因此是存在資源的競爭,是線程不安全的。
但是spring中大部分bean都是在方法內(nèi)部操作,例如:Controller、Service、Dao等,不會對bean的成員變量做查詢以外的操作,這種bean是線程安全的。如果非要在這些bean中定義成員變量并修改它,可以聲明@Scope("prototype")保證線程安全。
在spring內(nèi)部有一些bean會對成員變量操作,例如:RequestContextHolder等,這種bean一般通過ThreadLocal來解決線程安全的問題。
@Component 和 @Bean 的區(qū)別是什么?
- @Component注解作用于類;而@Bean作用于方法。
- @Component一般是用過類路徑來自動裝配到spring中;@Bean一般是在方法中產(chǎn)生一個bean,然后將這個bean交給spring管理。
- @Bean注解比@Component注解的自定義性更強,很多時候我們需要將第三方類庫中的bean裝配到spring中時,只能通過@Bean來實現(xiàn)。
SpringMVC 工作原理
- 客戶端發(fā)送請求,到達DispatcherServlet。
- DispatcherServlet根據(jù)請求信息調(diào)用HandlerMapping。
- HandlerMapping解析請求到對應(yīng)的Handler(Controller)后,開始由HandlerAdapter來處理。
- HandlerAdapter根據(jù)Handler調(diào)用真正的處理器來處理請求。
- 處理器處理完以后,返回一個ModelAndView對象。
- ViewResolver根據(jù)ModelAndView中的View查找實際的View。
- DispaterServlet將ModelAndView中的Model傳給View。
- 最后把實際的View返回給請求者。
在Spring容器初始化的過程中,所有定義的bean都會被初始化嗎?
不是,默認只初始化所有未初始化的非懶加載的單例Bean,scope為其它值的bean會在使用到的時候進行初始化,如prototype。
Spring如何解決循環(huán)依賴?
spring注入屬性方式有多種,但是只有一種循環(huán)依賴被解決:setter依賴注入。其他的注入方式,Spring也沒有辦法解決,只是拋出BeanCurrentlyInCreationException異常。
spring解決循環(huán)依賴的方式是采用三級緩存,未等bean創(chuàng)建完成之前就先將實例曝光出去,方便其他bean引用。
核心代碼:
//singletonObjects指單例對象的cache?(一級緩存)private?final?Map?singletonObjects?=?new?ConcurrentHashMap(256);//singletonFactories指單例對象工廠的cache(三級緩存)private?final?Map>?singletonFactories?=?new?HashMap>(16);//earlySingletonObjects指提前曝光的單例對象的cache(二級緩存)private?final?Map?earlySingletonObjects?=?new?HashMap(16);protected?Object?getSingleton(String?beanName,?boolean?allowEarlyReference)?{
???//從一級緩存獲取
???Object?singletonObject?=?this.singletonObjects.get(beanName);
???//isSingletonCurrentlyInCreation():判斷當(dāng)前單例bean是否正在創(chuàng)建中
???if?(singletonObject?==?null?&&?isSingletonCurrentlyInCreation(beanName))?{
??????synchronized?(this.singletonObjects)?{
?????????//從二級緩存獲取
?????????singletonObject?=?this.earlySingletonObjects.get(beanName);
?????????//allowEarlyReference:是否允許從singletonFactories中通過getObject拿到對象
?????????if?(singletonObject?==?null?&&?allowEarlyReference)?{
????????????//從三級緩存獲取
????????????ObjectFactory>?singletonFactory?=?this.singletonFactories.get(beanName);
????????????if?(singletonFactory?!=?null)?{
???????????????singletonObject?=?singletonFactory.getObject();
???????????????this.earlySingletonObjects.put(beanName,?singletonObject);
???????????????this.singletonFactories.remove(beanName);
????????????}
?????????}
??????}
???}
???return?(singletonObject?!=?NULL_OBJECT???singletonObject?:?null);
}
圖解:
A首先完成了初始化的第一步,并且將自己提前曝光到singletonFactories中,
此時進行初始化的第二步,發(fā)現(xiàn)自己依賴對象B,此時就嘗試去get(B),發(fā)現(xiàn)B還沒有被create,所以走create流程,
B在初始化第一步的時候發(fā)現(xiàn)自己依賴了對象A,于是嘗試get(A),嘗試一級緩存singletonObjects(沒有,因為A還沒初始化完全),嘗試二級緩存earlySingletonObjects(也沒有),嘗試三級緩存singletonFactories,由于A通過ObjectFactory將自己提前曝光了,所以B能夠通過ObjectFactory.getObject拿到A對象(此時A還沒有初始化完全),
B拿到A對象后順利完成了初始化階段1、2、3,完全初始化之后將自己放入到一級緩存singletonObjects中。
此時返回A中,A此時能拿到B的對象順利完成自己的初始化階段2、3,最終A也完成了初始化,進去了一級緩存singletonObjects中,而此時,由于B拿到了A的對象引用,所以B現(xiàn)在引用的A對象完成了初始化。
springboot原理,如何實現(xiàn)的自動裝配?
首先看啟動類上的@SpringBootApplication注解
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
????excludeFilters?=?{@Filter(
????type?=?FilterType.CUSTOM,
????classes?=?{TypeExcludeFilter.class}
),?@Filter(
????type?=?FilterType.CUSTOM,
????classes?=?{AutoConfigurationExcludeFilter.class}
)}
)
public?@interface?SpringBootApplication?{
再看里面的@EnableAutoConfiguration注解
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public?@interface?EnableAutoConfiguration?{
然后通過@Import注入AutoConfigurationImportSelector類,這個類通過實現(xiàn)DeferredImportSelector來重寫selectImports方法去加載META-INF/spring.factories這個外部文件,這個外部文件里面,默認有很多自動配置的類,這些類的定義信息將會被SpringBoot批量的注入到spring容器中,從而實現(xiàn)了自動裝配。
相關(guān)的starter和自定義starter都是根據(jù)這個實現(xiàn)的。
spring事務(wù)以及傳播機制
spring事務(wù)是封裝在數(shù)據(jù)庫事務(wù)之上的一種事務(wù)處理機制,它有兩種管理方式:編程式事務(wù)和聲明式事務(wù)。
spring事務(wù)的傳播機制有七種:REQUIRED、REQUIRES_NEW、NESTED、SUPPORTS、NOT_SUPPORTED、MANDATORY和NEVER。
詳細介紹參考以前的文章:傳送門
springboot打包成jar之后,怎么做到不重新打包修改他的properties配置文件?
Spring程序會按優(yōu)先級從下面這些路徑來加載application.properties配置文件
- 當(dāng)前目錄下的/config目錄
- 當(dāng)前目錄
- classpath里的/config目錄
- classpath 跟目錄
因此,要外置配置文件就很簡單了,在jar所在目錄新建config文件夾,然后放入配置文件,或者直接放在jar同級目錄
bootstrap.properties 和 application.properties 有何區(qū)別 ?
單純做 Spring Boot 開發(fā),可能不太容易遇到 bootstrap.properties 配置文件,但是在結(jié)合 Spring Cloud 時,這個配置就會經(jīng)常遇到了。
- bootstrap (. yml 或者 . properties):boostrap 由父 ApplicationContext 加載的,比 applicaton 優(yōu)先加載,配置在應(yīng)用程序上下文的引導(dǎo)階段生效。一般來說我們在 Spring Cloud 配置就會使用這個文件。且 boostrap 里面的屬性不能被覆蓋;
- application (. yml 或者 . properties):由ApplicatonContext 加載,用于 spring boot 項目的自動化配置。
Spring Boot 打成的 jar 和普通的 jar 有什么區(qū)別 ?
- Spring Boot 項目最終打包成的 jar 是可執(zhí)行 jar ,這種 jar 可以直接通過 java -jar xxx.jar 命令來運行。
- Spring Boot 的 jar 無法被其他項目依賴,主要還是他和普通 jar 的結(jié)構(gòu)不同。普通的 jar 包,解壓后直接就是包名,包里就是我們的代碼,而 Spring Boot 打包成的可執(zhí)行 jar 解壓后,在 \BOOT-INF\classes 目錄下才是我們的代碼,因此無法被直接引用。
掃一掃,關(guān)注我
Java面試系列-redis相關(guān)
2020-09-29
Java面試系列-線程相關(guān)(一)
2020-09-03
Java到底是引用傳遞還是值傳遞
2020-08-07
redis分布式鎖
2020-06-05
手摸手教你搭建免費圖床
2020-05-28
總結(jié)
以上是生活随笔為你收集整理的spring cloud每次修改必须重新打包_Java面试系列spring相关的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux连接外部库时候编译,交叉编译时
- 下一篇: springboot jar中没有主清单