Recently, I often need to do various interviews. I find that many candidates with several years of work experience know little about Spring, but only know how to use it. For example, an @Autowired principle can tell a lot about it.

Therefore, while the fairy is working overtime today, make a long story short and talk about this topic!

How do @autowired annotations automate assembly

The reason why the @autowired annotation can realize automatic assembly, mainly rely on Spring to provide processor AutowiredAnnotationBeanPostProcessor, The processor adds the processing of @AutoWired, @Inject and @Value annotations during initialization.

The processor implements the interface InstantiationAwareBeanPostProcessor, therefore can be instantiated in bean object, its members used the @autowired automatic assembly.

Source code reference is as follows:

public AutowiredAnnotationBeanPostProcessor(a) {
   // Add @autowired, @inject, @Value annotation
   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.}}Copy the code

When the processor was added

When constructing the Spring container, Spring will registered several built-in processor with the container object, including the AutowiredAnnotationBeanPostProcessor.

The source code can be directly see AnnotationConfigUtils registerAnnotationConfigProcessors method.

Source code reference is as follows:

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
      BeanDefinitionRegistry registry, @Nullable Object source) {

   // omit code...

   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));
   }

    // omit code...

   return beanDefs;
}
Copy the code

When was the handler called

Spring calls the doCreateBean method when creating a bean. Within the doCreateBean method, it calls the populateBean method, which determines whether the bean object needs to be auto-assembled. If so, iterate over the Spring container’s already injected processors one by one.

Source code reference is as follows:

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;
					// Execute the post-processor to populate the properties to complete the autowiring
					pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvs == null) {
						return;
					}
				}
			}
		}
	}
}
Copy the code

There are several ways of automatic assembly

Anyone who hasn’t used XML configuration for injection probably won’t be able to answer this question, but anyone who has read a Spring field book should know the point.

Spring currently supports three approaches, namely

  • AUTOWIRE_BY_NAME automatically assembles bean properties by name

  • AUTOWIRE_BY_TYPE automatically assembles bean properties by type

  • AUTOWIRE_CONSTRUCTOR automates assembly by constructor

The XML configuration injection can be toggled by specifying the following types, for example:

Extension: We do not recommend specifying autorotypes in XML, because developers cannot know all beans in Spring applications, and specifying them in this way can lead to uncertainty in the injected objects.

So using @autowired specifies what kind of autoassembly is going on

The answer is AUTOWIRE_NO, that is, not specified.

But in fact, the implementation of the source code is first assembled by type, if the matching implementation is multiple, additional strategies will be used.

How does Spring handle the @Autowried annotated interface if there are multiple implementations

Most people encounter this situation is a direct answer to report wrong, in fact, it is not.

If the interface has multiple implementations, Spring has its own set of policies:

  • Will look to see if there are any beans that use the @primary annotation
  • Select the highest Priority according to the @priority annotation Priority.
  • Judge by the name of the property and the beanName in Spring.

No complains, namely NoUniqueBeanDefinitionException anomalies.

The specific source code is as follows:

Which types are supported by @autowired injection

Anyone with a younger code age or who hasn’t read the source code can’t answer this question, and basically just knows that @AutoWired injects an object.

In fact, in addition to registering individual objects, @AutoWired supports injection of three additional types: array, collection, and Map.

Specific reference DefaultListableBeanFactory resolveMultipleBeans method

conclusion

These are not mandatory questions, but if you look at @Autowired, these are basically the questions. Well, fairies are out of work, so that’s it.

The original link: mp.weixin.qq.com/s/yAFMGOh5W…

Thank you for your support 👍👍👍!