Spring常問的真實大廠面試題匯總_第1頁
Spring常問的真實大廠面試題匯總_第2頁
Spring常問的真實大廠面試題匯總_第3頁
Spring常問的真實大廠面試題匯總_第4頁
Spring常問的真實大廠面試題匯總_第5頁
已閱讀5頁,還剩4頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、Spring常問的-真實大廠面試題匯總(含答案)面試題1Sprin中bean的循環(huán)依賴怎么解決?().首先說一下什么是Spring的循環(huán)依賴:“其實就是在進行g(shù)etBean的時候,A對象中去依賴B對象,而B對象又依賴C對象,但是對象C又去依賴A對象,結(jié)果就造成A、B、C三個對象都不能完成實例化,出現(xiàn)了循環(huán)依賴。就會出現(xiàn)死循環(huán),最終導(dǎo)致內(nèi)存溢出的錯誤。(二).如何去解決Spring的循環(huán)依賴呢?1先知道什么是Spring的“三級緩存”:就是下面的三個大的Map對象,因為Spring中的循環(huán)依賴的理論基礎(chǔ)其實是基于java中的值傳遞的,然后其實Spring中的單例對象的創(chuàng)建是分為三個步驟的:“cr

2、eateBeanlnstanee,其實第一步就是通過構(gòu)造方法去進行實例化對象。但是這一步只是實例對象而已,并沒有把對象的屬性也給注入進去c然后這一步就是進行注入實例對象的屬性,也就是從這步對springxml中指定的property進行populate最后一步其實是初始化XML中的init方法,來進行最終完成實例對象的創(chuàng)建。但是AfterPropertiesSet方法會發(fā)生循環(huán)依賴的步驟集中在第一步和第二步。singletonObjects指單例對象的cache(級緩存)privatefinalMapvString,Object>singletonObjects=newConcurren

3、tHashMap<String,Object>(256);singletonFactorie指單例對象工廠的cache(三級緩存)privatefinalMapvString,ObjectFactory<?>>singletonFactories=newHashMapvString,ObjectFactory<?>>(16);earlySingletonObjects旨提前曝光的單例對象的cache(二級緩存)privatefinalMapvString,Object>earlySingletonObjects=newHashMapvStr

4、ing,Object>(16);2. 然后是怎么具體使用到這個三級緩存的呢,或者說三級緩存的思路?°首先第一步是在Spring中會先去調(diào)用getSingleton(StringbeanName,booleanallowEarlyReference)來獲取想要的單例對象。°然后第一步會先進行通過singletonObjects這個一級緩存的集合中去獲取對象,如果沒有獲取成功的話并且使用isSingletonCurrentlylnCreation(beanName)去判斷對應(yīng)的單例對象是否正在創(chuàng)建中(也就是說當(dāng)單例對象沒有被初始化完全,走到初始化的第一步或者第二的時候),

5、如果是正在創(chuàng)建中的話,會繼續(xù)走到下一步°然后會去從earlySingletonObjects中繼續(xù)獲取這個對象,如果又沒有獲取到這個單例對象的話,并且通過參數(shù)傳進來的allowEarlyReference標(biāo)志,看是不是允許singletonFactories(三級緩存集合)去拿到該實例對象,如果allowEarlyReference為Ture的話,那么繼續(xù)下一步“此時上一步中并沒有從earlySingletonObjects二級緩存集合中拿到想要的實例對象,最后只能從三級緩存singletonFactories(單例工廠集合中)去獲取實例對象,°然后把獲取的對象通過Put(

6、beanName,singletonObject)放到earlySingletonObjects(二級緩存中),然后在再從singletonFactories(三級緩存)對象中的集合中把該對象給remove(beanName)出去?!案缴虾诵拇aprotectedObjectgetSingleton(StringbeanName,booleanallowEarlyReference)從一級緩存獲取ObjectsingletonObject=this.singletonObjects.get(beanName);if(singletonObject=null&&isSinglet

7、onCurrentlyInCreation(beanName)synchronized(this.singletonObjects)從二級緩存獲取singletonObject=this.earlySingletonObjects.get(beanName);if(singletonObject=null&&allowEarlyReference)從三級緩存獲取ObjectFactory<?>singletonFactory=this.singletonFactories.get(beanName);if(singletonFactory!=null)singlet

8、onObject=singletonFactory.getObject();this.earlySingletonObjects.put(beanName,singletonObject);this.singletonFactories.remove(beanName);HHHngletonObject!=NULLOBJECT?singletonObject:null).3. 總結(jié)一下為什么這么做就能解決Spring中的循環(huán)依賴問題。°其實在沒有真正創(chuàng)建出來一個實例對象的時候,這個對象已經(jīng)被生產(chǎn)出來了,雖然還不完美(還沒有進行初始化的第二步和第三步),但是已經(jīng)能被人認出來了(根據(jù)對象

9、引用能定位到堆中的對象),所以Spring此時將這個對象提前曝光出來讓大家認識,讓大家使用°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通過ObjectFa

10、ctory將自己提前曝光了,所以B能夠通過ObjectFactory.getObject拿到A對象(雖然A還沒有初始化完全,但是總比沒有好呀),B拿到A對象后順利完成了初始化階段1、2、3,完全初始化之后將自己放入到一級緩存singletonObjects中。此時返回A中,A此時能拿到B的對象順利完成自己的初始化階段2、3,最終A也完成了初始化,長大成人,進去了一級緩存singletonObjects中,而且更加幸運的是,由于B拿到了A的對象引用,所以B現(xiàn)在hold住的A對象也蛻變完美了!一切都是這么神奇!總結(jié):Spring通過三級緩存加上“提前曝光”機制,配合Java的對象引用原理,比較完美

11、地解決了某些情況下的循環(huán)依賴問題!面試題.Sprinc中bean的加載過程?首先從大的幾個核心步驟來去說明,因為Spring中的具體加載過程和用到的類實在是太多了。(1) 、首先是先從AbstractBeanFactory中去調(diào)用doGetBean(name,requiredType,finalObjectargs,booleantypeCheckOnly【這個是判斷進行創(chuàng)建bean還是僅僅用來做類型檢查】)方法,然后第一步要做的就是先去對傳入的參數(shù)name進行做轉(zhuǎn)換,因為有可能傳進來的name=“&XXX”之類,需要去除&符號(2) 、然后接著是去調(diào)用getSingleton

12、()方法,其實在上一個面試題中已經(jīng)提到了這個方法,這個方法就是利用“三級緩存”來去避免循環(huán)依賴問題的出現(xiàn)的。【這里補充一下,只有在是單例的情況下才會去解決循環(huán)依賴問題】(3) 、對從緩存中拿到的bean其實是最原始的bean,還未長大,所以這里還需要調(diào)用getObjectForBeanlnstance(ObjectbeanInstance,Stringname,StringbeanName,RootBeanDefinitionmbd)方法去進行實例化。(4) 、然后會解決單例情況下嘗試去解決循環(huán)依賴,如果isPrototypeCurrentlylnCreation(beanName)返回為tr

13、ue的話,會繼續(xù)下一步,否則thrownewBeanCurrentlylnCreationException(beanName);(5) 、因為第三步中緩存中如果沒有數(shù)據(jù)的話,就直接去parentBeanFactory中去獲取bean,然后判斷containsBeanDefinition(beanName)中去檢查已加載的XML文件中是否包含有這樣的bean存在,不存在的話遞歸去getBean()獲取,如果沒有繼續(xù)下一步(6) 、這一步是吧存儲在XML配置文件中的GernericBeanDifinition轉(zhuǎn)換為RootBeanDifinition對象。這里主要進行一個轉(zhuǎn)換,如果父類的bean

14、不為空的話,會一并合并父類的屬性(7) 、這一步核心就是需要跟這個Bean有關(guān)的所有依賴的bean都要被加載進來,通過剛剛的那個RootBeanDifinition對象去拿到所有的beanName,然后通過registerDependentBean(dependsOnBean,beanName)注冊bean的依賴(8)、然后這一步就是會根據(jù)我們在定義bean的作用域的時候定義的作用域是什么,然后進行判斷在進行不同的策略進行創(chuàng)建(比如isSingleton、isPrototype)(9)、這個是最后一步的類型裝換,會去檢查根據(jù)需要的類型是否符合bean的實際類型去做一個類型轉(zhuǎn)換°Spr

15、ing中提供了許多的類型轉(zhuǎn)換器面試題3.Spring中bean的生命周期?5"fgpe為prototypedriJ.汁冏期處給尖singlctoni'!堤存iTprineioc窖需J”/ApplicetranConlextAware的宴摘優(yōu)bean對談訓(xùn)用InitialiivigBsan的aFtfirPrfi方寸;凋HlInit-melbiod睿器其聞iMhtidisposableBeandderropnlesScld方法闌用destary-mefhod的方沆調(diào)用BtHnPDtFTOEi!swrfJ斤初蠟化方誡用日鼻anPostProcessor的畫初Sfi化方總(疋曲聃】調(diào)

16、H3t*ariFactcrvAwaresetBeanFactoryO方法煙用iicanNamcAwdrt泊5eCHKinPJaiTie(7fffi1. 首先會先進行實例化bean對象2. 然后是進行對bean的一個屬性進行設(shè)置3. 接著是對BeanNameAware(其實就是為了讓Spring容器來獲取bean的名稱)、BeanFactoryAware(讓bean的BeanFactory調(diào)用容器的服務(wù))、ApplicationContextAware(讓bean當(dāng)前的applicationContext可以來取調(diào)用Spring容器的服務(wù))4. 然后是實現(xiàn)BeanPostProcessor這個接

17、口中的兩個方法,主要是對調(diào)用接口的前置初始化postProcessBeforelnitialization5. 這里是主要是對xml中自己定義的初始化方法init-method="xxxx"進行調(diào)用6. 然后是繼續(xù)對BeanPostProcessor這個接口中的后置初始化方法進行一個調(diào)用postProcessAfterlnitialization()7. 其實到這一步,基本上這個bean的初始化基本已經(jīng)完成,就處于就緒狀態(tài)8. 然后就是當(dāng)Spring容器中如果使用完畢的話,就會調(diào)用destory()方法9. 最后會去執(zhí)行我們自己定義的銷毀方法來進行銷毀,然后結(jié)束生命周期補充

18、:當(dāng)在執(zhí)行第六步之后,如果Spring初始的這個bean的作用域是Prototype的話,之后的過程就不歸Spring來去管理了,直接就交給用戶就可以了。面試題4說一下Spring中的IOC核心思想和DI?面試題5說說Spring中事務(wù)實現(xiàn)原理?1. 事務(wù)的實現(xiàn)原理首先第一步是需要先打開EnableTransactionManagement是開啟注解式事務(wù)的事務(wù)2. 然后通過注解中套娃的TransactionManagementConfigurationSelector對象源碼Target(ElementType.TYPE)Retention(RetentionPolicy.RUNTIME)D

19、ocumentedImport(TransactionManagementConfigurationSelector.class)publicinterfaceEnableTransactionManagement用來表示默認使用DDynamicPro還是CLIProxybooleanproxyTargetClass()defaultfalse;表示以Proxybase布式實現(xiàn)AOP還是以Weavingbase冇式實現(xiàn)AOPAdviceModemode()defaultAdviceMode.PROXY;順序intorder()defaultOrdered.LOWEST_PRECEDENCE3.

20、 然后通過TransactionManangementConfigurationSelector這個對象去選擇一些Bean,向容器注冊BeanDefinition的(嚴格意義上Selector僅時選擇過程,注冊的具體過程是在ConfigurationClasspathPostProcessor解析時,調(diào)用ConfigurationClassParser觸發(fā))。主要的邏輯就是根據(jù)代理模式,注冊不同的BeanDefinition。對Proxy的模式而言,注入的有兩個AutoProxyRegistrarProxyTransactionManagementConfiguration4. AutoPro

21、xyRegistrarRegistrar同樣也是用來向容器注冊Bean的,在Proxy的模式下,它會調(diào)用AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);向容器中注冊InfrastructureAdvisorAutoProxyCreator。而這個類就是我們上文提到的AbstractAdvisorAutoProxyCreator的子類。從而,我們完成了我們的第一個條件一一AOP代理。ProxyTransactionManagementConfigurationProxyTransactionManagementConfig

22、uration是一個配置類,如果算上其繼承的父類,一共是聲明了四個類:TransactionalEventListenerFactoryBeanFactoryTransactionAttributeSourceAdvisorTransactionAttributeSourceTransactionInterceptor后三個類相對比較重要,我們一一分析5. 最關(guān)鍵的是這個TransactionInterceptorNullableprotectedObjectinvokeWithinTransaction(Methodmethod,NullableClass<?>targetcla

23、ss,finalInvocationcallbackinvocation)throwsThrowableTransactionAttributeSourcetas=getTransactionAttributeSource();finalTransactionAttributetxAttr=(tas!=null?tas.getTransactionAttribute(method,targetclass):null);finalTransactionManagertm=determineTransactionManager(txAttr);省略部分代碼獲取事物管理器PlatformTransa

24、ctionManagerptm=asPlatformTransactionManager(tm);finalStringjoinpointidentification=methodIdentification(method,targetclass,txAttr);if(txAttr=null|!(ptminstanceofCallbackPreferringPlatformTransactionManager)打開事務(wù)(內(nèi)部就是getTransactionStatus的過程)Transactioninfotxinfo=createTransactionIfNecessary(ptm,txAtt

25、r,joinpointidentification);ObjectretVajtry執(zhí)行業(yè)務(wù)邏輯ceedWithInvocation();catch(Throwableex)異?;貪LcompleteTransactionAfterThrowing(txInfo,ex);throwex;finallycleanupTransactioninfo(txinfo);省略部分代碼提交事物commitTransactionAfterReturning(txinfo);returnretVal;面試題說一下SpringMVC中的攔截器和Servlet中的filter有什么區(qū)別?

26、。首先最核心的一點他們的攔截側(cè)重點是不同的,SpringMVC中的攔截器是依賴JDK的反射實現(xiàn)的,SpringMVC的攔截器主要是進行攔截請求,通過對Handler進行處理的時候進行攔截,先聲明的攔截器中的preHandle方法會先執(zhí)行,然而它的postHandle方法(他是介于處理完業(yè)務(wù)之后和返回結(jié)果之前)和afterCompletion方法卻會后執(zhí)行。并且Spring的攔截器是按照配置的先后順序進行攔截的?!岸鳶ervlet的filter是基于函數(shù)回調(diào)實現(xiàn)的過濾器,F(xiàn)ilter主要是針對URL地址做一個編碼的事情、過濾掉沒用的參數(shù)、安全校驗(比較泛的,比如登錄不登錄之類)面試題.sprin

27、g容器的bean什么時候被實例化?(1) 如果你使用BeanFactory作為SpringBean的工廠類,則所有的bean都是在第一次使用該Bean的時候?qū)嵗?2) 如果你使用ApplicationContext作為SpringBean的工廠類,則又分為以下幾種情況:“如果bean的scope是singleton的,并且lazy-init為false(默認是false,所以可以不用設(shè)置),則ApplicationContext啟動的時候就實例化該Bean,并且將實例化的Bean放在一個map結(jié)構(gòu)的緩存中,下次再使用該Bean的時候,直接從這個緩存中取0如果bean的scope是single

28、ton的,并且lazy-init為true,則該Bean的實例化是在第一次使用該Bean的時候進行實例化°如果bean的scope是prototype的,則該Bean的實例化是在第一次使用該Bean的時候進行實例化面試題說一下Spring中AOP的底層是怎么實現(xiàn)的?,再說說一下動態(tài)代理和cglib區(qū)別?Spring中AOP底層的實現(xiàn)其實是基于JDK的動態(tài)代理和cglib動態(tài)創(chuàng)建類進行動態(tài)代理來實現(xiàn)的:1. 第一種基于JDK的動態(tài)代理的原理是:需要用到的幾個關(guān)鍵成員°InvocationHandler(你想要通過動態(tài)代理生成的對象都必須實現(xiàn)這個接口)。真實的需要代理的對象(幫

29、你代理的對象)°Proxy對象(是JDK中java.lang.reflect包下的)下面是具體如何動態(tài)利用這三個組件生成代理對象“(1)首先你的真是要代理的對象必須要實現(xiàn)InvocationHandler這個接口,并且覆蓋這個接口的invoke(ObjectproxyObject,Methodmethod,Objectargs)方法,這個Invoker中方法的參數(shù)的proxyObject就是你要代理的真實目標(biāo)對象,方法調(diào)用會被轉(zhuǎn)發(fā)到該類的invoke()方法,method是真實對象中調(diào)用方法的Method類,Objectargs是真實對象中調(diào)用方法的參數(shù)。(2)然后通過Proxy類去

30、調(diào)用newProxylnstance(classLoader,interfaces,handler)方法,classLoader是指真實代理對象的類加載器,interfaces是指真實代理對象需要實現(xiàn)的接口,還可以同時指定多個接口,handler方法調(diào)用的實際處理者(其實就是幫你代理的那個對象),代理對象的方法調(diào)用都會轉(zhuǎn)發(fā)到這里,然后直接就能生成你想要的對象類了。下面是Proxy調(diào)用newProxylnstanee的方法源碼publicstaticObjectnewProxyInstance(ClassLoaderloader,Class<?>interfaces,Invocati

31、onHandlerhthrows川egalArgumentException驗證傳入的nvocationHandler不能為空Objects.requireNonNull(h);復(fù)制代理類實現(xiàn)的所有接口finalClass<?>intfs=interfaces.clone();獲取安全管理器finalSecurityManagersm=System.getSecurityManager();進行一些權(quán)限檢驗if(sm!=null)checkProxyAccess(Reflection.getCallerClass(),loader,intfs);該方法先從緩存獲取代理類如果沒有再去

32、生成一個代理類Class<?>cl=getProxyClassO(loader,intfs);try進行一些權(quán)限檢驗if(sm!=null)checkNewProxyPermission(Reflection.getCallerClass(),cl);獲取參數(shù)類型是nvocationHandler.class的代理類構(gòu)造器finalConstructor<?>cons=cl.getConstructor(constructorParams);finalInvocationHandlerih=h;如果代理類是不可訪問的就使用特權(quán)將它的構(gòu)造器設(shè)置為可訪問if(!Modifi

33、er.isPublic(cl.getModifiers()AccessController.doPrivileged(newPrivilegedActior<Void>()publicVoidrun()cons.setAccessible(true);returnnull;);傳入InvocationHandler實例去構(gòu)造一個代理類的實例所有代理類都繼承自3roxy,因此這里會調(diào)用Proxy的構(gòu)造器將nvocationHandler引用傳入returncons.newInstance(newObjecth);catch(Exceptione)為了節(jié)省篇幅筆者統(tǒng)一用Exceptio

34、n捕獲了所有異常thrownewInternalError(e.toString(),e);面試題的幾種注入方式說一下?(1)構(gòu)造方法注入:<!-注冊userService-><beanid="userService"class="com.lyu.spring.service.impl.UserService"><constructor-argref="userDaoJdbc"></constructor-arg></bean><!-注冊jdbc實現(xiàn)的dao->&

35、lt;beanid="userDaoJdbc"class="com.lyu.spring.dao.impl.UserDaoJdbc"x/bean>注意的點:。如果有多個構(gòu)造參數(shù),那么與構(gòu)造方法參數(shù)列表參數(shù)的順序無關(guān)。如果有多個構(gòu)造方法且參數(shù)順序不同,那么會按第一個構(gòu)造方法進行注入(2)set方法注入:<!-注冊userService->vbeanid="userService"class="com.lyu.spring.service.impl.UserService"><!-寫法一-

36、><!-vpropertyname="UserDao"ref="userDaoMyBatis"></property>-><!-與法-><propertyname="userDao"ref="userDaoMyBatis"></property></bean><!-注冊mybatis實現(xiàn)的dao-><beanid="userDaoMyBatis"class="com.lyu.sprin

37、g.dao.impLUserDaoMyBatis"></bean>注意的點:。其實set方法的注入原理就是,spring會將name值的每個單詞首字母轉(zhuǎn)換成大寫,然后再在前面拼接上"set"構(gòu)成一個方法名,然后去對應(yīng)的類中查找該方法,通過反射調(diào)用,實現(xiàn)注入“如果通過set方法注入屬性,那么spring會通過默認的空參構(gòu)造方法來實例化對象,所以如果在類中寫了一個帶有參數(shù)的構(gòu)造方法,一定要把空參數(shù)的構(gòu)造方法寫上,否則spring沒有辦法實例化對象,導(dǎo)致報錯。(3)注解的方式注入:°Resource:java的注解,默認以byName的方式去匹配與屬性名相同的bean的id,如果沒有找到就會以byType的方式查找,如果byType查找到多個的話,使用Qualifier注解(spring注解)指定某個具體名稱的bean“Autowired:spring注解,默認是以byType的方式去匹配類型相同的bean,如果只匹配到一個,那么就直接注入該bean,無論要注入的bean的name是什么;如果匹配到多個,就會調(diào)用DefaultListableBeanFactory的determineAutowireCandidate方法來決定具體注入哪個bean°determineAutowireCandidate方法的內(nèi)容

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論