聊聊Autowired的常考面試題
金三銀四,很快又到了招聘旺季了,最近經常需要去做各種面試,發現很多幾年工作經驗的候選人,對Spring瞭解也是知之甚少,更多的只是會用,比如一個@Autowired原理都可以問倒一大片。
為此,趁著女朋友狗澤今天加班,長話短說的聊聊這個話題吧!
@Autowired註解是如何實現自動裝配的
@Autowired註解之所以可以實現自動裝配,主要是依賴Spring提供的處理器AutowiredAnnotationBeanPostProcessor,該處理器在初始化的時候便加入了對@Autowired、@Inject、@Value三個註解的處理;
該處理器實現了介面InstantiationAwareBeanPostProcessor,因此可以在bean物件例項化的時候,對其使用了@Autowired的成員進行自動裝配。
原始碼參考如下:
public AutowiredAnnotationBeanPostProcessor() {
// 加入了對@Autowired、@Inject、@Value三個註解的處理
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName(“javax.inject.Inject”, AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.info(“JSR-330 ‘javax.inject.Inject’ annotation found and supported for autowiring”);
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
該處理器何時被加入的
當構造Spring容器的時候,Spring會向容器註冊幾個內建的處理器物件,其中就包括了AutowiredAnnotationBeanPostProcessor。
原始碼可以直接看AnnotationConfigUtils.registerAnnotationConfigProcessors方法。
原始碼參考如下:
public static Set registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 省略程式碼…
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 省略程式碼…
return beanDefs;
}
該處理器是什麼時候被呼叫的
Spring在建立bean的時候會呼叫doCreateBean方法,在doCreateBean方法中會呼叫populateBean方法,該方法的作用便是先判斷是否該bean物件需要進行自動裝配,如果是的話再逐個遍歷呼叫Spring容器已經注入的處理器。
原始碼參考如下:
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (hasInstAwareBpps || needsDepCheck) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 執行後置處理器,填充屬性,完成自動裝配
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
}
}
自動裝配有幾種方式
沒有使用過xml配置進行注入的可能都無法回答這個問題,但是但凡看過Spring實戰類書籍的都應該知道這個知識點。
Spring目前支援三種方式,分別是
-
AUTOWIRE_BY_NAME 按名稱自動裝配bean屬性
-
AUTOWIRE_BY_TYPE 按型別自動裝配bean屬性
-
AUTOWIRE_CONSTRUCTOR 按構造器自動裝配
在xml配置注入的時候指定下型別即可進行切換,比如:
擴充:我司這邊不推薦使用在xml裡邊指定自動裝配型別,因為開發者無法對Spring應用中的所有Bean的情況都瞭如指掌,而透過這種方式指定會導致注入的物件也存在不確定性。
那麼使用@Autowired指定的是哪種自動裝配
答案是AUTOWIRE_NO,也就是沒有指定。
但是實際上看原始碼的實現其實率先透過型別來裝配,如果匹配到的實現是多個的,才會額外採用其他策略。
如果@Autowried註解的介面有多個實現,Spring是如何處理的
大部分人遇見這種情況都是直接回答報錯,其實不是的。
如果介面有多個實現,Spring有自己的一套策略:
-
會看看有沒有使用了@Primary註解的bean
-
根據@Priority註解優先順序選擇優先順序高的。
-
根據屬性的名稱和Spring中beanName來進行判斷。
再找不到才會報錯,也就是NoUniqueBeanDefinitionException異常。
具體實現原始碼如下:
@Autowired注入支援哪幾種型別
碼齡較短的或者沒有看過原始碼的都無法回答這個問題,基本上都只知道@Autowired注入一個物件。
而實際上@Autowired除了註冊單個物件外,還額外支援注入三種型別,分別是陣列、集合以及map型別。
具體參考DefaultListableBeanFactory.resolveMultipleBeans方法
總結
這幾個問題並非必考點,只是說如果考察@Autowired的話基本上問題就是這幾個了,好了,狗澤下班了,就先這樣吧。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2325/viewspace-2826986/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- golang 面試常考問題Golang面試
- 大廠常考的Spring面試題Spring面試題
- 大前端常見面試題:HTML常考知識點前端面試題HTML
- 面試 Linux 常考命令面試Linux
- 一文詳解面試常考的TopK問題面試TopK
- 京東前端二面常考手寫面試題(必備)前端面試題
- 面試常考演算法題之並查集問題面試演算法並查集
- Vue | 路由守衛面試常考Vue路由面試
- 【Java 開發面試】Mysql 面試考點/考題彙總Java面試MySql
- 【Java面試】@Resource 和 @Autowired 的區別Java面試
- Vue常見的面試題Vue面試題
- 集合常見的面試題面試題
- Java常見的面試題Java面試題
- 常見的JVM 面試題JVM面試題
- 100道JAVA面試題+JAVA面試題參考答案Java面試題
- 阿里面試Redis常考問題阿里面試Redis
- 【面試】面試常見問題整理面試
- 【Java面試】JSP常見面試題!JavaJS面試題
- 【Java面試】Servlet常見面試題!JavaServlet面試題
- 【Java面試】 Javascript常見面試題!JavaScript面試題
- JS面試考題記錄JS面試
- Linux 運維工程師面試真題-5-常考題目彙總Linux運維工程師面試
- bat等大公司常考java多執行緒面試題BATJava執行緒面試題
- 前端常見的部分面試題前端面試題
- 常見的Java面試問題Java面試
- 那些常見的面試題整理面試題
- 【Java面試】Java常見IO面試題!Java面試題
- 常見 React 面試題React面試題
- mybatis常見面試題MyBatis面試題
- spring常見面試題Spring面試題
- SpringMVC常見面試題SpringMVC面試題
- Docker常見面試題Docker面試題
- vue 常見面試題Vue面試題
- Spring常見面試題!Spring面試題
- Dubbo常見面試題面試題
- 前端常見面試題前端面試題
- ajax常見面試題面試題
- String常見面試題面試題