当前位置:网站首页>Smartinstantiationawarebeanpostprocessor of the extension point series determines which construction method to execute - Chapter 432
Smartinstantiationawarebeanpostprocessor of the extension point series determines which construction method to execute - Chapter 432
2022-07-01 05:49:00 【Wuxian】

Article history ( Cumulative 400+ An article )
《 The most complete in China Spring Boot One of series 》
《 The most complete in China Spring Boot The second series 》
《 The most complete in China Spring Boot Series three 》
《 The most complete in China Spring Boot Series 4 》
《 The most complete in China Spring Boot Series of 5、 ... and 》
SpringBoot/Spring The extension point BeanDefinitionRegistryPostProcessor - The first 427 piece
SpringBoot/Spring The expansion point series BeanFactoryPostProcessor - The first 428 piece SpringBoot Extension point series InstantiationAwareBeanPostProcessor simulation AOP - The first 429 piece
SpringBoot Configure file content encryption , Protect sensitive information - The first 431 piece
Wuxian : The master , You say? , When your code has multiple constructors ,Spring How do you know which constructor to execute ?

The master : This is due to Spring An extension point of SmartInstantiationAwareBeanPostProcessor.

Wuxian : The master , Then tell me about it .
The master : Let me give you a little introduction , The rest of the disciples explore by themselves .
Wuxian : Master leads in , Practice depends on oneself .

Reading guide
One 、SmartInstantiationAwareBeanPostProcessor summary
1.1 What is it? ?
SmartInstantiationAwareBeanPostProcessor Inherited from InstantiationAwareBeanPostProcessor;
however SmartInstantiationAwareBeanPostProcessor One more three methods .

1.2 The three methods are explained in detail
(1)getEarlyBeanReference
Get early exposure to bean quote , It is mainly used to solve the problem of circular reference .
getEarlyBeanReference: The trigger point occurs at postProcessAfterInstantiation after , When there is a cyclic dependency scenario , When bean After instantiation , In order to prevent circular dependence , The callback method is exposed ahead of time , be used for bean Post processing of instantiation . This method is triggered in the callback method exposed in advance .
(2)determineCandidateConstructors
testing Bean Constructor , Multiple candidate constructors can be detected , Then there are corresponding strategies to decide which one to use , Such as AutowiredAnnotationBeanPostProcessor The implementation will automatically scan through @Autowired/@Value Annotation constructor, which can complete constructor Injection
The execution time is : Object before instantiating .
determineCandidateConstructors: The trigger point occurs at postProcessBeforeInstantiation after , Used to determine the bean The function of constructor , It's time to go back bean List of all constructors for . Users can extend this point , From the definition, select the corresponding constructor to instantiate this bean.
(3)predictBeanType
forecast Bean The type of , Returns the first successful prediction Class type , If you can't predict the return null; When you call BeanFactory.getType(name) When passing Bean The definition cannot be obtained Bean The callback method is called to determine the type information ;BeanFactory.isTypeMatch(name, targetType) Used to detect a given name Bean Whether to match the target type ( For example, when dependency injection is used ).
predictBeanType: The trigger point occurs at postProcessBeforeInstantiation Before , This method is used to predict Bean The type of , Returns the first successful prediction Class type , If you can't predict the return null; When you call BeanFactory.getType(name) When passing bean The name of cannot be obtained bean The callback method is called to determine the type information .
1.3 Use scenarios
SmartInstantiationAwareBeanPostProcessor--determineCandidateConstructors Application scenario of processor :
When one bean When there are two construction methods in , A nonparametric construction method , A parametric construction method , that spring It's going on bean When initializing, call the parameterless constructor by default :
for example : as follows IndexServiceImpl There are two construction methods in

So in spring In the process of instantiation :

And if we want to execute the construction method with parameters , You need to add @Autowired Annotations can be :

Execution results : Find out spring Implemented the construction method with parameters

Spring The process of inferring the construction method : In the process , If it is inferred that there is a construction method with @Autowired annotation , that spring Will put it in a temporary variable , When judging whether the temporary variable is empty , If it's not empty , Convert this variable into a temporary array and return it , And if the construction method does not add @Autowired annotation , that spring You can't tell which to add to a temporary variable , So the last one is null, then spring According to the returned null To use the default constructor .
Two 、BeanFactoryPostProcessor Extension implementation
Mode one : Use @Configuration + @Bean Mode initialization
Mode two : Use @ComponentScan + @Component Mode initialization
Next, let's have a deeper understanding of several methods of this class through mode 2 .
2.1 Building an application
The application built in the previous section is used here , You can go on or rebuild a new one Spring Boot project .
2.2 Implementation interface InstantiationAwareBeanPostProcessor
Create a class , Implementation interface SmartInstantiationAwareBeanPostProcessor:
package com.kfit.config;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;import org.springframework.stereotype.Component;import java.lang.reflect.Constructor;/*** SmartInstantiationAwareBeanPostProcessor The extension point** @author Wuxian 「 official account SpringBoot」* @date 2022-06-22* @slogan The greatest truths are the simplest Enlightenment is in nature*/@Componentpublic class MySmartInstantiationAwareBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {/*** forecast Bean The type of , Returns the first successful prediction Class type , If you can't predict the return null* @param beanClass* @param beanName* @return* @throws BeansException*/@Overridepublic Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {System.out.println("MySmartInstantiationAwareBeanPostProcessor.predictBeanType,beanName:"+beanName);return null;}/*** Select the appropriate constructor , For example, the target object has multiple constructors , Some customization can be done here , Select the appropriate constructor** @param beanClass : beanClass The parameter represents the type of the target instance* @param beanName : beanName Is the target instance in Spring In container name* @return : The return value is an array of constructors , If you return null, Will execute the next PostProcessor Of determineCandidateConstructors Method ; Otherwise, select the PostProcessor Select the constructor* @throws BeansException*/@Overridepublic Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {System.out.println("MySmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors,beanName:"+beanName);return null;}/*** Get early exposure to bean quote , It is mainly used to solve the problem of circular reference* ( Only singleton objects will call this method )* @param bean* @param beanName* @return* @throws BeansException*/@Overridepublic Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {System.out.println("MySmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference,beanName:"+beanName);return null;}}
2.3 Start the test
Run the project , Look at the effect :

…

3、 ... and 、AutowiredAnnotationBeanPostProcessor
Next, let's say AutowiredAnnotationBeanPostProcessor Let's see SmartInstantiationAwareBeanPostProcessor How is it used .
3.1 Key code
The following is a AutowiredAnnotationBeanPostProcessor application SmartInstantiationAwareBeanPostProcessor Key code :
@Override@Nullablepublic Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)throws BeanCreationException {// Let's check for lookup methods here...if (!this.lookupMethodsChecked.contains(beanName)) {try {ReflectionUtils.doWithMethods(beanClass, method -> {Lookup lookup = method.getAnnotation(Lookup.class);if (lookup != null) {Assert.state(this.beanFactory != null, "No BeanFactory available");LookupOverride override = new LookupOverride(method, lookup.value());try {RootBeanDefinition mbd = (RootBeanDefinition)this.beanFactory.getMergedBeanDefinition(beanName);mbd.getMethodOverrides().addOverride(override);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(beanName,"Cannot apply @Lookup to beans without corresponding bean definition");}}});}catch (IllegalStateException ex) {throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);}this.lookupMethodsChecked.add(beanName);}// Quick check on the concurrent map first, with minimal locking.Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);if (candidateConstructors == null) {// Fully synchronized resolution now...synchronized (this.candidateConstructorsCache) {candidateConstructors = this.candidateConstructorsCache.get(beanClass);if (candidateConstructors == null) {Constructor<?>[] rawCandidates;try {// Reflection gets all constructorsrawCandidates = beanClass.getDeclaredConstructors();}catch (Throwable ex) {throw new BeanCreationException(beanName,"Resolution of declared constructors on bean Class [" + beanClass.getName() +"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);}// Candidate construction methodsList<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);Constructor<?> requiredConstructor = null;Constructor<?> defaultConstructor = null;// This seems to be Kotlin For use , Don't worry about it.Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);int nonSyntheticConstructors = 0;// Traverse these constructorsfor (Constructor<?> candidate : rawCandidates) {// Determine whether the construction method is syntheticif (!candidate.isSynthetic()) {nonSyntheticConstructors++;}else if (primaryConstructor != null) {continue;}// Check to see if there is @Autowired annotation// If there are multiple construction methods , You can use the annotation @Autowired To specify which constructor to useAnnotationAttributes ann = findAutowiredAnnotation(candidate);if (ann == null) {Class<?> userClass = ClassUtils.getUserClass(beanClass);if (userClass != beanClass) {try {Constructor<?> superCtor =userClass.getDeclaredConstructor(candidate.getParameterTypes());ann = findAutowiredAnnotation(superCtor);}catch (NoSuchMethodException ex) {// Simply proceed, no equivalent superclass constructor found...}}}// Yes @Autowired The situation ofif (ann != null) {if (requiredConstructor != null) {throw new BeanCreationException(beanName,"Invalid autowire-marked constructor: " + candidate +". Found constructor with 'required' Autowired annotation already: " +requiredConstructor);}boolean required = determineRequiredStatus(ann);if (required) {if (!candidates.isEmpty()) {throw new BeanCreationException(beanName,"Invalid autowire-marked constructors: " + candidates +". Found constructor with 'required' Autowired annotation: " +candidate);}requiredConstructor = candidate;}candidates.add(candidate);}// The case of nonparametric constructorselse if (candidate.getParameterCount() == 0) {// The constructor has no arguments , Set as the default constructordefaultConstructor = candidate;}}// Come here , All construction methods have been cycled// When the candidate is not emptyif (!candidates.isEmpty()) {// Add default constructor to list of optional constructors, as fallback.if (requiredConstructor == null) {if (defaultConstructor != null) {candidates.add(defaultConstructor);}else if (candidates.size() == 1 && logger.isInfoEnabled()) {logger.info("Inconsistent constructor declaration on bean with name '" + beanName +"': single autowire-marked constructor flagged as optional - " +"this constructor is effectively required since there is no " +"default constructor to fall back to: " + candidates.get(0));}}candidateConstructors = candidates.toArray(new Constructor<?>[0]);}// Class construction methods only 1 individual , And the construction method has multiple parameterselse if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {candidateConstructors = new Constructor<?>[] {rawCandidates[0]};}// There's no going in here , because primaryConstructor = nullelse if (nonSyntheticConstructors == 2 && primaryConstructor != null &&defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};}// There's no going in here , because primaryConstructor = nullelse if (nonSyntheticConstructors == 1 && primaryConstructor != null) {candidateConstructors = new Constructor<?>[] {primaryConstructor};}else {// If the method goes here , I just can't find a suitable construction method//1. Class defines more than one constructor , And there's no @Autowired , You may enter herecandidateConstructors = new Constructor<?>[0];}this.candidateConstructorsCache.put(beanClass, candidateConstructors);}}} // If you don't find it here , Will return null, Instead of returning an empty arrayreturn (candidateConstructors.length > 0 ? candidateConstructors : null);}
3.2 Code instructions
The above method is relatively long , But look carefully , It can be roughly divided into several steps :
(1) Get all constructors of the class
(2) Traversal construction method
- There is only one parameterless constructor , Then return to null.
- There is only one parametric construction method , Return this constructor .
- There are multiple construction methods and there is no @Autowired, here spring Then it will be encircled , I don't know which one to use . The post processor here , Translate it , It is called intelligent selection construction method post processor . When you can't choose , Simply return null.
- There are several ways to construct , And marked on one of the methods @Autowired , The constructor of this annotation will be returned
- There are several ways to construct , And marked on several methods @Autowired, be spring It throws an exception , spring Will think , You assigned me a few , Are you mistaken .
I am me , It's fireworks of different colors .
I am me , It's a different little apple .à Wukong College :https://t.cn/Rg3fKJD
There is Spring Boot Related courses ! Click on 「 Read the original 」 To view the !
SpringBoot video :http://t.cn/A6ZagYTi
SpringBoot Communication platform :https://t.cn/R3QDhU0
SpringSecurity5.0 video :http://t.cn/A6ZadMBe
ShardingJDBC Sub database and sub table :http://t.cn/A6ZarrqS
Distributed transaction solutions :http://t.cn/A6ZaBnIr
JVM Memory model tuning practice :http://t.cn/A6wWMVqG
Spring Beginner to master :https://t.cn/A6bFcDh4
Big talk design pattern love you :https://dwz.cn/wqO0MAy7
边栏推荐
- 从底层结构开始学习FPGA----RAM IP的定制与测试
- Some errors encountered in MySQL data migration
- SystemVerilog学习-06-类的封装
- 【医学分割】u2net
- excel动态图表
- C语言初阶——牛客网精选好题
- OpenGL ES: (1) OpenGL ES的由来 (转)
- C language beginner level - realize the minesweeping game
- It's not that you have a bad mind, but that you haven't found the right tool
- First defined here occurs during QT compilation. Causes and Solutions
猜你喜欢

Learn the customization and testing of fpga---ram IP from the bottom structure

Continue to learn MySQL
SSM的教务管理系统(免费源码获取)

论文学习记录随笔 多标签之GLOCAL

如何添加葫芦儿派盘

FPGA - 7系列 FPGA内部结构之Clocking -02- 时钟布线资源

4GB大文件,如何实时远程传输和共享?

Boot + jsp University Community Management System (with source Download Link)

千万不要把笔记视频乱放!

C语言初阶——实现扫雷游戏
随机推荐
【QT】qt加减乘除之后,保留小数点后两位
Enter an expression (expressed as a string) and find the value of this expression.
Some errors encountered in MySQL data migration
Ssgssrcsr differences
【考研高数 自用】高数第一章基础阶段思维导图
葫芦儿 APP 使用帮助
SQL必会题之留存率
数据治理:数据治理框架(第一篇)
Basic electrician knowledge 100 questions
HCM 初学 ( 一 ) - 简介
Summary of common components of applet
bat操作ftp上传下载命令
Brief description of activation function
输入一个表达式(用字符串表示),求这个表达式的值。
excel動態圖錶
FPGA - 7系列 FPGA内部结构之Clocking -02- 时钟布线资源
穿越派 你的数据云行
Beauty of Mathematics - Application of Mathematics
[QT] QT after addition, subtraction, multiplication and division, two decimal places are reserved
[medical segmentation] u2net