The underlying principle of Sao @Autowired of words, spring automatic assembly

Antecedent Review

Spring BeanPostProcessor expand the interface, we look at its underlying implementation talked about spring underlying support for BeanPostProcessor, and know BeanPostProcessor of two methods: postProcessBeforeInitialization, execution timing postProcessAfterInitialization, did not see the small partners can look back and see Look. Originally spring automatic assembly is going to put on the blog post to explain in detail, but then think of space may be too large, since you are feeling out, then I will not say Ming dark any more, why not put to explain the papers, because space is really too much. Well, we get down to business, why not put the papers in terms of space but the cause of

First, the main reason is that I found a mistake! Committed any wrong?

I for granted! Granted that automatic assembly is implemented in AutowiredAnnotationBeanPostProcessor of postProcessBeforeInitialization or postProcessAfterInitialization, we look at the class inheritance diagram AutowiredAnnotationBeanPostProcessor

The underlying principle of Sao @Autowired of words, spring automatic assembly

It is indirectly a BeanPostProcessor, we could look at it two ways (in the parent class InstantiationAwareBeanPostProcessorAdapter)

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
 return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
 return bean;
}
复制代码

Actually nothing dry, simply return bean; when their own deep that awareness was overthrown, it feels really shoot the dog

So automatic assembly can not put a BeanPostProcessor speak, had to open two to tell apart, we all know: a horse is not sweet!

Automatic assembling simple example

Let's look at a simple example of automatic assembly, a complete example code: spring-boot-BeanPostProcessor

AnimalServiceImpl

@Service
public class AnimalServiceImpl implements IAnimalService {
 @Autowired
 private Dog dog;
 @Resource
 private Cat cat;
 @Inject
 private Pig pig;
 @Override
 public void printName() {
 System.out.println(dog.getName());
 System.out.println(cat.getName());
 System.out.println(pig.getName());
 }
}
复制代码

AnimalTest

@RunWith(SpringRunner.class)
@SpringBootTest(classes={Application.class})
public class AnimalTest {
 @Autowired
 private IAnimalService animalService;
 @Test
 public void test() {
 animalService.printName();
 }
}
复制代码

operation result

The underlying principle of Sao @Autowired of words, spring automatic assembly

We will only Dog in AnimalConfig in instances Cat, Pig registered to the spring container, then why AnimalServiceImpl example can be applied directly to these examples, and we do not manually assign these instances to AnimalServiceImpl instance of it? This is actually autowire spring offer, although we do not have to manually these instances assigned to AnimalServiceImpl instance, but we found a few more notes on the property instance AnimalServiceImpl of: @ Autowired, @ Resource, @ Inject, spring through these annotations automatically completion of the injection property of the instance, without the need for us to manually go to the assignment; then spring is how to achieve automatic assembly of it? We look down slowly (Note: The text mainly @Autowired example to explain)

Analytical automatic assembly Source

AutowiredAnnotationBeanPostProcessor instantiation and registration

Anyway, AutowiredAnnotationBeanPostProcessor after all, or a BeanPostProcessor, then it is instantiated and registered (registration to the spring of beanFactory) procedures are the same instantiation and registration of BeanPostProcessor, during start of spring, the refresh time context (refresh), it will when calling registerBeanPostProcessors (beanFactory) and the instantiation of the method of registration BeanPostProcessor subsequent recall finishBeanFactoryInitialization (beanFactory) examples of non-delayed loading the bean single embodiment, may use said registered BeanPostProcessor

AutowiredAnnotationBeanPostProcessor constructor worth a look

public AutowiredAnnotationBeanPostProcessor() {
 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.
 }
}
复制代码

By default, AutowiredAnnotationBeanPostProcessor support @Autowired and @Value, if there is java.inject.Inject classpath (that is, the introduction of javax.inject.jar), it also supports @Inject notes, is not with us some initial awareness Different?

Will support annotations placed autowiredAnnotationTypes property, the property will be used follow-up

Examples of bean and dependency injection

By default, the spring will spring bean container as non-lazy-init singleton processes (except for some special bean), that is to say it will be individually instantiate the bean during startup of the spring, and these bean dependency injection; when we actually use these bean directly used on the line, do not go instantiated, do not go to the injection of dependencies the bean, spring is not very powerful?

Not specifically say so, we are ready to peanuts, melon seeds and beer, and the play is about to begin

We first find the correct entry, and then omitted boring foreplay with the following figure, direct access to a climax: doCreateBean

The underlying principle of Sao @Autowired of words, spring automatic assembly

doCreateBean follows

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
 throws BeanCreationException {
 // Instantiate the bean.
 BeanWrapper instanceWrapper = null;
 if (mbd.isSingleton()) {
 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
 }
 if (instanceWrapper == null) {
 // 创建bean实例
 instanceWrapper = createBeanInstance(beanName, mbd, args);
 }
 final Object bean = instanceWrapper.getWrappedInstance();
 Class<?> beanType = instanceWrapper.getWrappedClass();
 if (beanType != NullBean.class) {
 mbd.resolvedTargetType = beanType;
 }
 // Allow post-processors to modify the merged bean definition.
 // 允许后置处理器来修改bean定义
 synchronized (mbd.postProcessingLock) {
 if (!mbd.postProcessed) {
 try {
 // 调用MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法
 // AutowiredAnnotationBeanPostProcessor实现了MergedBeanDefinitionPostProcessor,即MergedBeanDefinitionPostProcessor的MergedBeanDefinitionPostProcessor会被调用
 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
 }
 catch (Throwable ex) {
 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 "Post-processing of merged bean definition failed", ex);
 }
 mbd.postProcessed = true;
 }
 }
 // Eagerly cache singletons to be able to resolve circular references 立即缓存单例以便能够解析循环引用
 // even when triggered by lifecycle interfaces like BeanFactoryAware.
 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
 isSingletonCurrentlyInCreation(beanName));
 if (earlySingletonExposure) {
 if (logger.isDebugEnabled()) {
 logger.debug("Eagerly caching bean '" + beanName +
 "' to allow for resolving potential circular references");
 }
 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
 }
 // Initialize the bean instance.
 Object exposedObject = bean;
 try {
 // 填充bean,包含依赖注入
 populateBean(beanName, mbd, instanceWrapper);
 // 初始化bean,BeanPostProcessor的两个方法在此中被调用
 exposedObject = initializeBean(beanName, exposedObject, mbd);
 }
 catch (Throwable ex) {
 if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
 throw (BeanCreationException) ex;
 }
 else {
 throw new BeanCreationException(
 mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
 }
 }
 if (earlySingletonExposure) {
 Object earlySingletonReference = getSingleton(beanName, false);
 if (earlySingletonReference != null) {
 if (exposedObject == bean) {
 exposedObject = earlySingletonReference;
 }
 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
 String[] dependentBeans = getDependentBeans(beanName);
 Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
 for (String dependentBean : dependentBeans) {
 if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
 actualDependentBeans.add(dependentBean);
 }
 }
 if (!actualDependentBeans.isEmpty()) {
 throw new BeanCurrentlyInCreationException(beanName,
 "Bean with name '" + beanName + "' has been injected into other beans [" +
 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
 "] in its raw version as part of a circular reference, but has eventually been " +
 "wrapped. This means that said other beans do not use the final version of the " +
 "bean. This is often the result of over-eager type matching - consider using " +
 "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
 }
 }
 }
 }
 // Register bean as disposable.
 try {
 registerDisposableBeanIfNecessary(beanName, bean, mbd);
 }
 catch (BeanDefinitionValidationException ex) {
 throw new BeanCreationException(
 mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
 }
 return exposedObject;
}
复制代码

We look posProcessMergedBeanDefinition focus on methods and methods populateBean

posProcessMergedBeanDefinition

The underlying principle of Sao @Autowired of words, spring automatic assembly

You read the annotation can be seen on the bean field and method, and determines whether the annotation in autowiredAnnotationTypes, if the field will be encapsulated into AutowiredFiledElement objects, the method AutoWiredMethodElement encapsulated into objects, and place the object InjectionMetadata Set <InjectedElement > checkedElements property, and finally the InjectionMetadata object cache to AutowiredAnnotationBeanPostProcessor the Map <String, InjectionMetadata> injectionMetadataCache property; it means to be @Autowried bean in (of course @ Value, @ Inject) modified field, method to find out , packaged into InjectionMetadata objects and cached, it's that simple. This is not just a figure above animalServiceImpl bean, spring in all non-lazy loading of bean will take this creation process. Is not very simple, is not it motivated the

populateBean

The underlying principle of Sao @Autowired of words, spring automatic assembly

Call AutowiredAnnotationBeanPostProcessor of postProcessPropertyValues ​​method to obtain the current dependency information from injectionMetadataCache bean, such as animalServiceImpl dependent dog, this question pig (someone might be:? Cat cat it is @Resource modified, but not by AutowiredAnnotationBeanPostProcessor support @Resource subsequent speaks who support), then one by one into the target will depend bean bean (the dog, pig instance injected into animalServiceImpl instance); dependent bean come from it? Or obtained from beanFactory, if not present, then went back to the creation of the bean to rely bean (dog, pig) created out exactly the same process and create animalServiceImpl instance, also said that rely on animalServiceImpl instance injection process will dog , pig or create objects out, one by one rather than wait until spring bean to instantiate the process turn dog, pig just instantiate dog, pig, and that the subsequent turn of dog, pig how to do the time, spring will create a cached bean the next time he took directly from the cache. The figure is only a demo Field, Method also not too bad, not demonstrated, are achieved through reflection.

to sum up

1, bean creation and initialization

(1) instanceWrapper = createBeanInstance (beanName, mbd, args) to create the target bean instance;

(2) applyMergedBeanDefinitionPostProcessors (mbd, beanType, beanName) to find the target bean-dependent;

(3) populateBean (beanName, mbd, instanceWrapper) filling the bean target, dependency injection is completed; (where a circular dependency, can be self interested pondering the next)

(4) initializeBean (beanName, exposedObject, mbd) to initialize the target bean

2, automatic assembly and automatic configuration

Automatic configuration Generally talking spring of @Autowired, is one of the characteristics of the spring, and automatic configuration is springboot of @Configuration, is one of the characteristics of springboot

3, Spring supports a few notes several automatic assembly

@ Autowired, @ Inject, @ Resource and @Value, should use the most is @Autowired (at least I was so), @ Inject and @Value also supported by AutowiredAnnotationBeanPostProcessor, and is supported by @Resource CommonAnnotationBeanPostProcessor (also supports @PostConstruct , @ PreDestroy notes, etc.)

About @Value and @Autowired, I do not know if you know the difference between them is not clear you can see: Spring: @Value vs. @Autowired spring or official documents, under the summary: @Value> = @Autowired, just in the usual application, more @ value is used to inject the configuration values ​​(eg: @Value ( "$ {db.url}")), and is injected @Autowired bean object


Guess you like

Origin juejin.im/post/5d822b02f265da03da24cc5a