Spring Source Analysis (16) Preparing to create a bean

Source: Internet
Author: User
Tags throwable

This paper analyzes the source code of Spring 5.0.6 with "Spring Source depth analysis". If there is any description of the error, please correct me.

We cannot expect to complete a complex logic in a function, and we have followed so many of the spring code, and have experienced so many functions, and more or less found some rules: a really working function is actually started with do, such as Dogetobjectfromfactorybean, and the function that gives us the illusion, such as Getobjectfromfactorybean, is actually doing some co-ordination work from a global perspective. This rule is no exception for Createbean, so let's look at what is being done in the Createbean function.

/*** Central method of this class:creates a bean instance, * Populates the bean instance, applies post-processors, etc. * @see#doCreateBean*/@OverrideprotectedObject Createbean (String beanname, rootbeandefinition mbd, @Nullable object[] args)throwsbeancreationexception {if(logger.isdebugenabled ()) {Logger.debug ("Creating Instance of Beans '" + beanname + "'"); } rootbeandefinition Mbdtouse=mbd; //Make sure Bean class was actually resolved at the this point, and//clone The bean definition in case of a dynamically resolved Class//which cannot is stored in the shared merged bean definition. //Lock class, according to the class attribute of the set or according to ClassName to parse classClass<?> Resolvedclass =Resolvebeanclass (mbd, beanname); if(Resolvedclass! =NULL&&!mbd.hasbeanclass () && mbd.getbeanclassname ()! =NULL) {Mbdtouse=Newrootbeandefinition (mbd);    Mbdtouse.setbeanclass (Resolvedclass); }    //Prepare method overrides. //methods for validating and preparing for coverage    Try{mbdtouse.preparemethodoverrides (); }    Catch(Beandefinitionvalidationexception ex) {Throw Newbeandefinitionstoreexception (Mbdtouse.getresourcedescription (), Beanname,"Validation of method overrides failed", ex); }    Try {        //Give Beanpostprocessors a chance to return a proxy instead of the target bean instance. //give Beanpostprocessors a chance to return an agent to replace the real instanceObject Bean =resolvebeforeinstantiation (Beanname, mbdtouse); if(Bean! =NULL) {            returnBean; }    }    Catch(Throwable ex) {Throw Newbeancreationexception (Mbdtouse.getresourcedescription (), Beanname,"Beanpostprocessor before instantiation of Bean failed", ex); }    Try{Object beaninstance=Docreatebean (Beanname, Mbdtouse, args); if(logger.isdebugenabled ()) {Logger.debug ("Finished creating instance of beans '" + beanname + "'"); }        returnbeaninstance; }    Catch(Beancreationexception |implicitlyappearedsingletonexception ex) {        //A previously detected exception with proper bean creation context already,//or illegal singleton state to is communicated up to defaultsingletonbeanregistry.        Throwex; }    Catch(Throwable ex) {Throw Newbeancreationexception (Mbdtouse.getresourcedescription (), Beanname,"Unexpected exception during bean creation", ex); }}

From the code we can summarize the function of the completion of the specific steps and functions.

(1) The class is parsed according to the class attribute set or according to Dassname.

(2) Mark and verify the override attribute.

Many readers may not know the effect of this method because there is no configuration like Override-method in the spring configuration, so what is this method really for?

There is really no such configuration in spring, but if you read the previous section, you may find that there are lookup~method and Replace-method in the spring configuration, Override-method. The loading of these two configurations is actually to store the configuration in the Methodoverrides attribute in beandefinition, and this function is actually for the two configurations.

(3) Apply the pre-initialization of the post-processor, to resolve whether the specified bean has pre-initialization short-circuiting operation.

(4) Create a bean.

We first look at the logical implementation of the override attribute tag and validation.

First, handling the override attribute

View the Preparemethodoverrides method of the Abstractbeandeflnition class in the source code:

/*** Validate and prepare the method overrides defined for this bean. * Checks for existence of a method with the Specif IED name. * @throwsBeandefinitionvalidationexception in case of validation failure*/ Public voidPreparemethodoverrides ()throwsbeandefinitionvalidationexception {//Check that lookup methods exists.    if(Hasmethodoverrides ()) {Set<MethodOverride> overrides =getmethodoverrides (). Getoverrides (); synchronized(Overrides) { for(Methodoverride mo:overrides) {preparemethodoverride (MO); }        }    }}/*** Validate and prepare the given method override. * Checks for existence of a method with the specified name, * Marki Ng it as not overloaded if none found. * @parammo The Methodoverride object to validate *@throwsBeandefinitionvalidationexception in case of validation failure*/protected voidPreparemethodoverride (methodoverride mo)throwsbeandefinitionvalidationexception {//gets the number of corresponding method names in the corresponding class    intCount =Classutils.getmethodcountforname (Getbeanclass (), Mo.getmethodname ()); if(count = = 0) {        Throw NewBeandefinitionvalidationexception ("Invalid method Override:no method with Name '" + mo.getmethodname () + "' on class [" + Getbeanclassname () + "]"); }    Else if(Count = = 1) {        //Mark Override as not overloaded, to avoid the overhead of arg type checking. //tag Methodoverride temporarily not overwritten, avoiding the overhead of parameter type checkingMo.setoverloaded (false); }}

With the code of the above two functions, can you appreciate the function it is going to implement? As mentioned before, there are Lookup-method and Replace-method two configuration functions in spring configuration, and the load of these two configurations is to store the configuration uniformly in the Methodoverrides attribute in Beandefmition. The two function implementation principle is actually when the bean is instantiated, if the existence of the Methodoverrides attribute is detected, it dynamically generates the agent for the current bean and uses the corresponding interceptor for the bean to do the enhancement, and the related logic implementation is described in detail in the Bean Instantiation section.

However, it is mentioned here that, for a method match, if there are several overloaded methods in a class, the function calls and enhancements need to be matched against the parameter type to finally confirm which function is currently called. However, spring will be part of the matching work done here, if the current class is only one of the methods, then set the method is not overloaded, so that in subsequent calls can be directly used to find the method, without the need for the method parameter matching validation, but also in advance to verify the existence of the method, is with stone.

Second, the instantiation of the pre-processing

This method is used Resolvebeforelnstantiation (Bcanname, mbd) to do some pre-processing of the attributes in Beandefmigiton before actually invoking the Docreate method to create an instance of the bean. Of course, regardless of whether there is a corresponding logical implementation we can understand, because the real logical implementation before and after the processing function is also extensible embodiment, but this is not the most important, in the function also provides a short-circuit judgment, this is the most critical part.

if NULL ) {    return  Bean;}

When the result returned after a pre-processing is not NULL, the result is returned directly from the creation of the subsequent bean. Although this feature is easily overlooked, it plays a vital role, and the AOP function we know is based on the judgment here.

/*** Apply before-instantiation post-processors, resolving whether there are a * before-instantiation shortcut for the SP Ecified Bean. * @paramBeanname The name of the bean *@paramMBD The bean definition for the bean *@returnThe shortcut-determined bean instance, or {@codenull} if none*/@NullableprotectedObject Resolvebeforeinstantiation (String beanname, rootbeandefinition mbd) {Object Bean=NULL; //if it has not been resolved    if(!Boolean.FALSE.equals (mbd.beforeinstantiationresolved)) {        //Make sure beans class is actually resolved at the this point.        if(!mbd.issynthetic () &&hasinstantiationawarebeanpostprocessors ()) {Class<?> TargetType =Determinetargettype (Beanname, mbd); if(TargetType! =NULL) {Bean= applybeanpostprocessorsbeforeinstantiation(TargetType, beanname); if(Bean! =NULL) {Bean= applybeanpostprocessorsafterinitialization(Bean, beanname); } }} mbd.beforeinstantiationresolved= (Bean! =NULL); }    returnBean;}

The most intriguing of this approach is undoubtedly the two methods Applybeanpostprocessorsbeforelnstantiation and applybeanpostprocessorsafterlnitialization. The two methods are very simple to implement, nothing more than a postprocessbeforelnstantiation method and a post processor for all instantiationawarebeanpostprocessor types in a post-processor Beanpostprocessor the invocation of the Postprocessafterlnitialization method.

1. Post-processor application before instantiation

Called before the Bean is instantiated, which is the process of converting absractbeandefinition to Beanwrapper. Give the subclass a chance to modify the beandefinition, that is, when the program passes through this method, the bean may not be the bean we think it is, but it might become a processed agent bean, possibly generated by cglib, or generated by other techniques. This is described in detail in the 7th chapter, and we only need to know that the post-processor method is called before the Bean is instantiated for processing.

/*** Apply instantiationawarebeanpostprocessors to the specified bean definition * (by class and name), invoking their { @codePostprocessbeforeinstantiation} methods. * <p>any returned object would be used as the bean instead of actually instantiating * the target bean. A {@codeNULL} return value from the post-processor would * result in the target bean being instantiated. * @paramBeanclass the class of the bean to be instantiated *@paramBeanname The name of the bean *@returnThe Bean object to use instead of a default instance of the target bean, or {@codeNULL} *@seeinstantiationawarebeanpostprocessor#postprocessbeforeinstantiation*/@NullableprotectedObject Applybeanpostprocessorsbeforeinstantiation (class<?>Beanclass, String beanname) {     for(Beanpostprocessor bp:getbeanpostprocessors ()) {if(BPinstanceofinstantiationawarebeanpostprocessor) {Instantiationawarebeanpostprocessor IBP=(Instantiationawarebeanpostprocessor) BP; Object result=ibp.postprocessbeforeinstantiation (Beanclass, beanname); if(Result! =NULL) {                returnresult; }        }    }    return NULL;}
2. Post-processor application after instantiation

When it comes to getting a singleton bean from the cache, the rule in spring is to ensure that the Postprocessafterinitialization method of the registered post-processor is applied to the bean as much as possible after the bean's initialization. Because if the returned bean is not empty, then it will not go through the creation of the normal bean again, so the Postprocessafterlnitialization method of the post-processor can only be applied here.

@Override PublicObject Applybeanpostprocessorsafterinitialization (Object Existingbean, String beanname)throwsbeansexception {Object result=Existingbean;  for(Beanpostprocessor beanprocessor:getbeanpostprocessors ()) {Object current=beanprocessor.postprocessafterinitialization (result, beanname); if(Current = =NULL) {            returnresult; } result=Current ; }    returnresult;}

Spring Source Analysis (16) Preparing to create a bean

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.