@Can the autowired annotation be used in the static attribute? The autowired injection is null on the static property

@Can the Autowired annotation be used in the static attribute?

The answer is No. let's test:

The log information is clear, indicating that static cannot be copied by @ Autowired. Why? Let's find out why now.

First, set up our test environment,

User1 class

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

User2 class

@Componentpublic 
class User2 {}

AppConfig class

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

Test class

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

Then locate the code at the entry of dependency injection

At this time, our beanName is User1 class. We need to inject User1 class, and then we enter this method

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 instantiawarebeanpostprocessors 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 determines whether you have implemented instantiawarebeanpostprocessor yourself. If so, and returns false, //Spring will not continue to execute. Generally, it will not use if (! MBD. Issynthetic() & & hasinstantiationawarebeanpostprocessors()) {for (beanpostprocessor BP: getbeanpostprocessors()) {if (BP instanceof instantiationawarebeanpostprocessor) {instantiationawarebeanpostprocessor IBP = (instantiationawarebeanpostprocessor) BP; if (! IBP. Postprocessafterinstance (BW. Getwrappedinstance(), beanname)) {return;}}}} / / judge whether the property has been assigned propertyvalues. PVS = (MBD. Haspropertyvalues()? MBD. Getpropertyvalues(): null)// Judge the mode of attribute implantation. The default is 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();} / / here is the work of property injection through the post processor. For (beanpostprocessor BP: getbeanpostprocessors()) {if (BP instanceof instantiawarebeanpostprocessor) {instantiawarebeanpostprocessor 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);    }  }

Here are two for loops. Let's focus on the second for loop and find that the post processor is

Then click in

The first line of code here is to obtain our data information and encapsulate it in the way of InjectionMetadata. After obtaining InjectionMetadata, we can inject attributes in the way of reflection. We have described it in detail in the previous Spring source code chapter and will not describe it. Let's enter the findautowiring metadata method to see how it is obtained of

We can see what information is encapsulated in the InjectionMetadata, including our user3 attribute. Note that user3 is not statically modified, and user2 is statically modified, but there is no user2 attribute here. Remember this first, and then we will see that our metadata is obtained through the injectionMetadataCache cache, indicating that our static is When storing the cache, we mask our static attribute. Next, we will verify our conjecture.

When does Spring mask the static attribute?

We locate the code in the AbstractAutowireCapableBeanFactory.doCreateBean method

Follow in

Retrace

You can see that we have returned to our find method. Click in and notice that the red line below indicates that we are looking for the attribute of user1 class

Then here we focus on the injectionMetadataCache cache

At this time, there is no meta information of user1 in the cache. We follow up again

First, see ReflectionUtils.doWithLocalFields here. Let's click in

You can see that two of our properties are obtained here, one is static and the other is normal. Then we go back to the buildauutowiringmetadata method. Note that the file here is a function, which will call back the code here

We can see that if our attribute is static, Spring will abandon it directly,

We can see that it has been verified that Spring discards the static attribute here. As for why it discards the static attribute? I guess we need to return to some knowledge of the JVM. We all know that static is class oriented, and Spring is usually oriented to ordinary singleton objects. If we assign a value to the static attribute in the singleton object, it will affect me I personally think that Spring doesn't want to see the values of other objects of this class, which is also unscientific.

Tags: Java Spring Back-end

Posted on Sun, 31 Oct 2021 03:16:48 -0400 by greepit