日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring框架你敢写精通,面试官就敢问@Autowired注解的实现原理

發(fā)布時間:2025/3/21 javascript 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring框架你敢写精通,面试官就敢问@Autowired注解的实现原理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

面試官:Spring框架中的@Autowired注解可以標(biāo)注在哪些地方?

小小白:@Autowired注解可以被標(biāo)注在構(gòu)造函數(shù)、屬性、setter方法或配置方法上,用于實現(xiàn)依賴自動注入。

面試官:有沒有研究過@Autowired注解的實現(xiàn)原理?

小小白:看過它的實現(xiàn)源碼。

面試官:那你說一下@Autowired注解的工作原理?

小小白:@Autowired注解的作用是由AutowiredAnnotationBeanPostProcessor實現(xiàn)的,查看該類的源碼會發(fā)現(xiàn)它實現(xiàn)了MergedBeanDefinitionPostProcessor接口,進而實現(xiàn)了接口中的postProcessMergedBeanDefinition方法,@Autowired注解正是通過這個方法實現(xiàn)注入類型的預(yù)解析,將需要依賴注入的屬性信息封裝到InjectionMetadata類中,InjectionMetadata類中包含了哪些需要注入的元素及元素要注入到哪個目標(biāo)類中,在Spring容器啟動的過程中初始化單例bean的時候通過populateBean方法實現(xiàn)對屬性的注入。

public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {if (beanType != null) {InjectionMetadata metadata = this.findAutowiringMetadata(beanName, beanType, (PropertyValues)null);metadata.checkConfigMembers(beanDefinition);}}public class InjectionMetadata {private static final Log logger = LogFactory.getLog(InjectionMetadata.class);private final Class<?> targetClass;private final Collection<InjectedElement> injectedElements;private volatile Set<InjectedElement> checkedElements;

面試官:AutowiredAnnotationBeanPostProcessor類的postProcessMergedBeanDefinition方法是在什么時候被調(diào)用的?

小小白:Spring容器在啟動的時候會執(zhí)行AbstractApplicationContext類的refresh方法,在refresh方法執(zhí)行的過程中先注冊AutowiredAnnotationBeanPostProcessor,然后在對非延遲初始化的單例bean進行初始化時,會間接調(diào)用。具體實現(xiàn)細節(jié)分析如下。

public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.// 重點看這里:在這里對AutowiredAnnotationBeanPostProcessor注冊registerBeanPostProcessors(beanFactory);// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.// 重點看這里:對非延遲初始化的單例bean進行初始化finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}} }

refresh方法中registerBeanPostProcessors(beanFactory)完成了對AutowiredAnnotationBeanPostProcessor的注冊,當(dāng)執(zhí)行finishBeanFactoryInitialization(beanFactory)方法對非延遲初始化的單例bean進行初始化時,會執(zhí)行到AbstractAutowireCapableBeanFactory類的doCreateBean方法,在這個方法中有如下這么一段代碼。

synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}mbd.postProcessed = true;} }

在這段代碼中會執(zhí)行applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName),深入到這個applyMergedBeanDefinitionPostProcessors方法中。

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof MergedBeanDefinitionPostProcessor) {MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);}} }

可以看到,if的條件判斷邏輯是否屬于MergedBeanDefinitionPostProcessor,而AutowiredAnnotationBeanPostProcessor正好實現(xiàn)了MergedBeanDefinitionPostProcessor接口,所以在這里調(diào)用AutowiredAnnotationBeanPostProcessor類的postProcessMergedBeanDefinition方法。

面試官:你在說一下注入的過程?

小小白:使用AutowiredFieldElement實現(xiàn)對標(biāo)注在屬性上的注入,使用AutowiredMethodElement對標(biāo)注在方法上的注入。注入過程:根據(jù)需要注入的元素的描述信息,按類型或名稱查找需要的依賴值,如果依賴沒有實例化先實例化依賴,然后使用反射進行賦值。

面試官:@Resource或者@Autowired注解有什么區(qū)別?

小小白:雖然@Resource和@Autowired都可以書寫標(biāo)注在屬性或者該屬性的setter方法之上,但是@Resource默認是按照名稱來裝配注入的,只有當(dāng)找不到與名稱匹配的bean才會按照類型來裝配注入;@Autowired默認是按照類型裝配注入的,默認情況下它要求依賴對象必須存在如果允許為null,可以設(shè)置它required屬性為false,如果想按照名稱來注入,則需要結(jié)合@Qualifier一起使用;@Resource注解是由JDK提供,而@Autowired是由Spring提供。

總結(jié)

以上是生活随笔為你收集整理的Spring框架你敢写精通,面试官就敢问@Autowired注解的实现原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。