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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

@Autowired注解能用在static属性吗?autowired注入static属性上为null

發(fā)布時(shí)間:2025/3/12 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 @Autowired注解能用在static属性吗?autowired注入static属性上为null 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

@Autowired注解能用在static屬性嗎?

答案是否定的,我們來(lái)測(cè)試下:

日志信息已經(jīng)很明確了,表示static不能被@Autowired進(jìn)行復(fù)制。為什么呢?我們現(xiàn)在就來(lái)一起了解其原因。

首先將我們的測(cè)試環(huán)境搭建好,

User1類(lèi)

@Componentpublic class User1 { @Autowired private static User2 user2; @Autowired private User2 user3; }

User2類(lèi)

@Componentpublic class User2 {}

AppConfig類(lèi)

@Configuration@ComponentScan("staticDemo") /*@EnableAspectJAutoProxy*/ /*@Import(MyImportBeanDefinitionRegistrar.class)*/ public class AppConfig {}

Test類(lèi)

public class Test { public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext(AppConfig.class); } }

然后將代碼定位在依賴注入的入口

此時(shí)我們的beanName是User1類(lèi),我們需要注入U(xiǎn)ser1類(lèi),然后我們進(jìn)入這個(gè)方法

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { if (bw == null) { if (mbd.hasPropertyValues()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { // Skip property population phase for null instance. return; } } // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. //Spring判斷你是不是自己實(shí)現(xiàn)了InstantiationAwareBeanPostProcessor,如果實(shí)現(xiàn)了,而且返回false, // Spring就不會(huì)繼續(xù)執(zhí)行了,一般不會(huì)用到 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } } //判斷是否已經(jīng)對(duì)屬性賦值 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); //判斷屬性植入的模式,默認(rèn)NO int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } //這里才是通過(guò)后置處理器完成屬性注入的工作 for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } }

這里有兩個(gè)for循環(huán),我們關(guān)注第二個(gè)for循環(huán),找到后置處理器是

然后點(diǎn)進(jìn)去

這里第一行代碼就是獲取我們的數(shù)據(jù)信息,并且用InjectionMetadata的方式進(jìn)行封裝,獲取InjectionMetadata后就可以通過(guò)反射的方式進(jìn)行屬性注入了,這里在前面的Spring源碼章節(jié)我們已經(jīng)詳細(xì)介紹了,就不再敘述。我們進(jìn)入這個(gè)findAutowiringMetadata方法,瞧一瞧他是如何獲取的,

我們看到InjectionMetadata封裝了哪些信息,其中包含了我們的user3這個(gè)屬性,注意這個(gè)user3是沒(méi)有static修飾的,user2是被static修飾了的,而這里確沒(méi)有user2這個(gè)屬性,先記住這一點(diǎn),然后我們?cè)倏次覀兊膍etadata是通過(guò)injectionMetadataCache緩存獲取的,說(shuō)明一個(gè)我們的static是在存放緩存的時(shí)候就將我們的static屬性屏蔽掉,接下來(lái)我們就驗(yàn)證我們的猜想。

Spring何時(shí)屏蔽static屬性?

我們將代碼定位在AbstractAutowireCapableBeanFactory.doCreateBean方法

跟蹤進(jìn)去

再跟蹤

可以看到已經(jīng)回到了我們find方法,點(diǎn)進(jìn)去,注意下面的紅線表示我們這里是找的user1類(lèi)的屬性

然后這里我們關(guān)注的是injectionMetadataCache緩存

此時(shí)緩存里并沒(méi)有user1的元信息,我們?cè)俅胃M(jìn)

首先看到這里ReflectionUtils.doWithLocalFields,我們點(diǎn)進(jìn)去

可以看到這里獲取了兩個(gè)我們的屬性,一個(gè)是靜態(tài)屬性一個(gè)是常態(tài)屬性,然后我們?cè)倩氐絙uildAutowiringMetadata方法,注意這里的filed是函數(shù)試變成,它會(huì)回調(diào)這里的代碼

我們就可以看到如果我們的屬性是static,那么Spring會(huì)直接拋棄,

可以看到我們已經(jīng)得到了驗(yàn)證,Spring就是在這里拋棄了static的屬性,至于為什么要拋棄static屬性呢?筆者猜測(cè)這里需要回到JVM的一些知識(shí),我們都知道static是面向類(lèi)級(jí)別,而Spring通常是面向普通的單例對(duì)象,如果我們將單例的對(duì)象中static屬性賦值,那么就會(huì)影響我們這個(gè)類(lèi)的其他對(duì)象的值,個(gè)人認(rèn)為這是Spring不希望看到的,這也是不科學(xué)的。

總結(jié)

以上是生活随笔為你收集整理的@Autowired注解能用在static属性吗?autowired注入static属性上为null的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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