🚀 High quality resource sharing 🚀
Learning route guidance (click to unlock) | Knowledge orientation | Crowd positioning |
---|---|---|
🧡 Python actual wechat ordering applet 🧡 | Progressive class | This course is the perfect combination of Python Flash + wechat applet. From project construction to Tencent cloud deployment and launch, it creates a full stack ordering system. |
💛 Python quantitative trading practice 💛 | beginner | Take you hand in hand to build an easy to expand, safer and more efficient quantitative trading system |
So far, we know that Spring has five methods to create Bean objects, namely:
- Create using the getObject method of FactoryBean
- It is created using the postprocessbeforeinstance method of instantiaawarebeanpostprocessor, a sub interface of BeanPostProcessor
- Set the Supplier property of BeanDefinition to create
- Set the factory method of BeanDefinition to create
- Create using the whole process: getBean -- > dogetbean -- > createbean -- > docreatebean reflection
As described in the previous 4, we will introduce the fifth one. We know that if you use reflection to create, you must know to use the constructor for instantiation, because the constructor can be used to set the parameters.
SmartInstantiationAwareBeanPostProcessor interface
As mentioned earlier, InstantiationAwareBeanPostProcessor is used to instantiate objects in advance, while SmartInstantiationAwareBeanPostProcessor is a sub interface of InstantiationAwareBeanPostProcessor. What is it used for?
Source code in createBeanInstance method:
// Omit code // Specify that the constructor is from the BeanPostProcessor, and the corresponding is AutowiredAnnotationBeanPostProcessor // It is a subclass of SmartInstantiationAwareBeanPostProcessor and is implemented using determineCandidateConstructors // Parse constructor Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } // Omit code
Click in:
protected Constructor[] determineConstructorsFromBeanPostProcessors(@Nullable Class beanClass, String beanName) throws BeansException { if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; // Determine candidate constructors Constructor[] ctors = ibp.determineCandidateConstructors(beanClass, beanName); if (ctors != null) { return ctors; } } } } return null; }
You can see that this interface is used to parse the constructor of BeanClass. The implementation class of SmartInstantiationAwareBeanPostProcessor, autowirediannotationbeanpostprocessor, is used to parse and determine the appropriate constructor, focusing on the @ Autowired annotation, as well as the @ Value annotation and @ Lookup annotation.
After the constructor is parsed, the autowireConstructor method is called for instantiation. A constructor resolver will be created during parsing. It is also used when parsing factoryMethod. This class uses the method of instantiateUsingFactoryMethod, and parsing factoryMethod is more complex. It is necessary to judge whether it is a static factory creation or an instance factory creation, The construction analysis of automatic assembly is relatively simple, which is solved by autowireConstructor method.
Finally, the construction method and parameters are resolved and instantiated:
// Instantiate using appropriate construction methods and construction parameters bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
Instantiation:
private Object instantiate( String beanName, RootBeanDefinition mbd, Constructor constructorToUse, Object[] argsToUse) { try { // Cglibsubclassing instantiationstrategy is generally used to obtain the instantiation strategy InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy(); if (System.getSecurityManager() != null) { return AccessController.doPrivileged((PrivilegedAction) () -> strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse), this.beanFactory.getAccessControlContext()); } else { // Start instantiation return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse); } } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean instantiation via constructor failed", ex); } } public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner, final Constructor ctor, Object... args) { if (!bd.hasMethodOverrides()) { if (System.getSecurityManager() != null) { // use own privileged to change accessibility (when security is on) AccessController.doPrivileged((PrivilegedAction) () -> { ReflectionUtils.makeAccessible(ctor); return null; }); } // Instantiation class, reflection call return BeanUtils.instantiateClass(ctor, args); } else { // If the method is overridden, the lookup method and replace method return instantiateWithMethodInjection(bd, beanName, owner, ctor, args); } }
If none of the previous parses are to Bean, the parameterless constructor will be used for parsing:
// Omit code // Preferred constructors for default construction? // The preferred constructor is the default creation method, and the @ Primary annotation is used as the preferred object creation method ctors = mbd.getPreferredConstructors(); if (ctors != null) { return autowireConstructor(beanName, mbd, ctors, null); } // No special handling: simply use no-arg constructor. // Call the parameterless constructor to instantiate the object return instantiateBean(beanName, mbd);
Instantiate Bean:
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) { try { Object beanInstance; if (System.getSecurityManager() != null) { beanInstance = AccessController.doPrivileged( (PrivilegedAction) () -> getInstantiationStrategy().instantiate(mbd, beanName, this), getAccessControlContext()); } else { // Instantiate the object and create it using reflection beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this); } // Create a Bean wrapper BeanWrapper bw = new BeanWrapperImpl(beanInstance); // Initializes the wrapper for the Bean initBeanWrapper(bw); return bw; } catch (Throwable ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); } }
Here we can see that the Bean is wrapped by using factoryMethod and autowireConstructor to resolve the constructor for instantiation or using parameterless constructor for instantiation. What's the role of this packaging?
Function of BeanWrapper
Let's first look at how the previous method creates BeanWrapper:
Factory method parsing, ConstructorResolver#instantiateUsingFactoryMethod method:
public BeanWrapper instantiateUsingFactoryMethod( String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) { // Create a Bean wrapper BeanWrapperImpl bw = new BeanWrapperImpl(); this.beanFactory.initBeanWrapper(bw); // factoryBean Object factoryBean; // factory class Class factoryClass; // Identifies whether the factory is static boolean isStatic; // Omit code }
Smartinstantiaawarebeanpostprocessor subclass AutowiredAnnotationBeanPostProcessor resolves the constructor, and then uses ConstructorResolver#autowireConstructor to execute:
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, @Nullable Constructor[] chosenCtors, @Nullable Object[] explicitArgs) { // Create a wrapper BeanWrapperImpl bw = new BeanWrapperImpl(); // Initialize wrapper this.beanFactory.initBeanWrapper(bw); // Constructor Constructor constructorToUse = null; // Construction parameters ArgumentsHolder argsHolderToUse = null; // Construction parameters to be used Object[] argsToUse = null; // If the explicit construction parameter is not empty, it is assigned to the construction parameter to be instantiated if (explicitArgs != null) { argsToUse = explicitArgs; } // Omit code }
Finally, the conversion services ConversionService and PropertyEditorRegistry will be registered. One is used for property type conversion and the other is used for property value resolution:
protected void initBeanWrapper(BeanWrapper bw) { // Get the transformation service and put it in the wrapper of the bean bw.setConversionService(getConversionService()); // Register custom attribute editor registerCustomEditors(bw); }
In the previous article, I introduced how to use these two, and also customized the Attribute Editor and type conversion. You can go to see them if you need them:
https://blog.csdn.net/redwinter/p/16167214.html and https://blog.csdn.net/redwinter/p/16241328.html
Here, the instantiation of Bean is completed, and then look at the source code:
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; // Get the Bean object of FactoryBean from the cache if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // Instantiate object instanceWrapper = createBeanInstance(beanName, mbd, args); } // Get Bean object from wrapper Object bean = instanceWrapper.getWrappedInstance(); // Get Bean type from wrapper Class beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { // Merge Bean applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } } }
Click in:
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class beanType, String beanName) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof MergedBeanDefinitionPostProcessor) { MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp; // Perform merge BeanDefinition bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName); } } }
You can see that there is an interface MergedBeanDefinitionPostProcessor, which is also a sub interface of BeanPostProcessor. What is it used for?
MergedBeanDefinitionPostProcessor interface
Click to find that the implementation classes of this interface are all related to annotations. The most important is the CommonAnnotationBeanPostProcessor implementation class. Two annotations are set in the constructor: @PostConstruct and @PreDestroy. One is called after initialization, and the other is called when the container is destroyed.
To be continued