Bean loading (10) attribute injection

Source: Internet
Author: User
Tags addall

In understanding the cycle of dependence, we have repeatedly mentioned Populatebean this function, but also how much understanding of the function is the main function of the property is filled, then how to implement the fill it?

protected void Populatebean (String beanname, rootbeandefinition mbd, beanwrapper bw) {propertyvalues PVS = Mbd.getpropert Yvalues (), if (bw = = NULL) {if (!pvs.isempty ()) {throw new Beancreationexception (Mbd.getresourcedescription (), Beanname, "Cannot apply property values to null instance");} else {//Skip property population phase for null Instance.return;}} Give any instantiationawarebeanpostprocessors the opportunity to modify the//state of the bean before properties is s Et. This can is used, for example,//to support styles of field Injection.boolean continuewithpropertypopulation = True;if (!m Bd.issynthetic () && hasinstantiationawarebeanpostprocessors ()) {for (Beanpostprocessor BP: Getbeanpostprocessors ()) {if (BP instanceof Instantiationawarebeanpostprocessor) { Instantiationawarebeanpostprocessor IBP = (instantiationawarebeanpostprocessor) bp;//return value for whether to continue populating beanif (! Ibp.postprocessafterinstantiation (Bw.getwrappedinstance (), beanname)) {continuewithpropertypopulation = FalsE;break;}}}} Terminates subsequent execution if (!continuewithpropertypopulation) {return;} if the post processor issues a stop fill command if (mbd.getresolvedautowiremode () = = Rootbeandefinition.autowire_by_name | | Mbd.getresolvedautowiremode () = = Rootbeandefinition.autowire_by_type) {mutablepropertyvalues NewPvs = new Mutablepropertyvalues (PVS);//ADD property values based on Autowire by name if applicable.//automatically injects if by name (Mbd.getresolvedau Towiremode () = = Rootbeandefinition.autowire_by_name) {autowirebyname (beanname, MBD, BW, Newpvs);} Add property values based-Autowire by type if applicable.//automatically injected by type if (mbd.getresolvedautowiremode () = = Rootbeandefi Nition. Autowire_by_type) {Autowirebytype (beanname, MBD, BW, Newpvs);} PVs = Newpvs;} The post processor has been initialized with a Boolean Hasinstawarebpps = Hasinstantiationawarebeanpostprocessors ();//requires a dependency check for Boolean Needsdepcheck = ( Mbd.getdependencycheck ()! = Rootbeandefinition.dependency_check_none); if (Hasinstawarebpps | | needsDepCheck) { propertydescriptor[] Filteredpds = Filterpropertydescriptorsfordependencycheck (BW, Mbd.allowcaching), if (Hasinstawarebpps) {for (Beanpostprocessor bp:getbeanpostprocessors ()) {if (BP instanceof Instantiationawarebeanpostprocessor) {Instantiationawarebeanpostprocessor IBP = ( Instantiationawarebeanpostprocessor) bp;//post-processing of all properties that require dependency checking PVs = Ibp.postprocesspropertyvalues (PVs, Filteredpds, Bw.getwrappedinstance (), beanname); if (PVs = = null) {return;}}}} if (Needsdepcheck) {//dependency check, corresponding to Depends-on property, 3.0 has deprecated this attribute checkdependencies (Beanname, MBD, Filteredpds, PVS);}} Apply the attribute to the bean//To populate the Beanwrapper in all protertyvalues. Applypropertyvalues (Beanname, MBD, BW, PVS);}

Several of the above steps are of interest to us, they are dependency injection (autowirebyname/autowirebytype) and attribute padding, followed by further analysis of the implementation details of these features.

1.autowireByName

The above mentioned is based on the injection type (BYNAME/BYTYPE), extracting the dependent bean and storing it uniformly into the propertyvalues, we see how byname is implemented:

/** * In the incoming parameter bw, find the bean that has been loaded and instantiate it recursively, and add it to the PVS. */protected void Autowirebyname (String beanname, abstractbeandefinition mbd, beanwrapper bw, mutablepropertyvalues PVS) {//Look for attributes that require dependency injection in bw string[] propertynames = unsatisfiednonsimpleproperties (mbd, BW); for (String PropertyName: PropertyNames) {if (Containsbean (PropertyName)) {///recursive initialization related beanobject bean = Getbean (propertyname);p Vs.add ( PropertyName, Bean);//Registered Dependent Registerdependentbean (PropertyName, Beanname); if (logger.isdebugenabled ()) {Logger.debug ("Added autowiring by name from Bean name '" + Beanname + "' via property '" + propertyname + "' to Bean named '" + Propert Yname + "'");}}  else {if (logger.istraceenabled ()) {Logger.trace ("Not autowiring property '" + propertyname + "' of Bean '" + beanname + "' By name:no matching Bean found ");}}}

2.autowireByType

Autowirebytype and Autowirebyname are similar in terms of complexity to our understanding and use, but the complexity of achieving functionality is different

protected void Autowirebytype (String beanname, abstractbeandefinition mbd, beanwrapper bw, mutablepropertyvalues PVs) { TypeConverter converter = Getcustomtypeconverter (); if (converter = = null) {converter = bw;} set<string> autowiredbeannames = new linkedhashset<string> (4);//Search for bw in which the dependency injection property is required string[] PropertyNames = Unsatisfiednonsimpleproperties (mbd, BW); for (String Propertyname:propertynames) {try {propertydescriptor PD = Bw.getpropertydescriptor (PropertyName);//Don ' t try autowiring by type for type object:never makes sense,//even if it te Chnically is a unsatisfied, Non-simple property.if (! Object.class.equals (Pd.getpropertytype ())) {//Probe the set method of the specified property Methodparameter Methodparam = Beanutils.getwritemethodparameter (PD);//Do not allow eager init for type matching in case of a prioritized post-processor . Boolean eager =! PriorityOrdered.class.isAssignableFrom (Bw.getwrappedclass ());D ependencydescriptor desc = new Autowirebytypedependencydescriptor (Methodparam, eager);//parsing specified BeannaThe property of me matches the value, and the parsed property name is stored in autowiredbeannames, Object autowiredargument = resolvedependency (desc, Beanname, Autowiredbeannames, Converter); if (autowiredargument! = null) {Pvs.add (propertyname, autowiredargument);} for (String autowiredbeanname:autowiredbeannames) {//Register dependent Registerdependentbean (Autowiredbeanname, beanname);  Logger.isdebugenabled ()) {Logger.debug ("autowiring by type from bean name '" + Beanname + "' via Property '" +propertyname + "' to Bean named '" + Autowiredbeanname + "'");}} Autowiredbeannames.clear ();}} catch (Beansexception ex) {throw new Unsatisfieddependencyexception (Mbd.getresourcedescription (), Beanname, PropertyName, ex);}}}

Based on the first step of the name and based on the property, the first step is to look for properties that require dependency injection in bw, then traverse these properties and look for the type-matching bean, the most complex of which is finding the type-matching bean.

The resolvedependency function is encapsulated in a logical implementation that looks for type matching. ublic Object resolvedependency (dependencydescriptor descriptor, String beanname, set<string> Autowiredbeannames, TypeConverter TypeConverter) throws Beansexception {

Descriptor.initparameternamediscovery (Getparameternamediscoverer ()); if (Descriptor.getdependencytype (). Equals ( Objectfactory.class) {//objectfactory Class injection special handling return new Dependencyobjectfactory (descriptor, beanname);} else if (Descriptor.getdependencytype (). Equals (Javaxinjectproviderclass)) {// Special handling of Javaxinjectproviderclass class injection return new Dependencyproviderfactory (). Createdependencyprovider (Descriptor, Beanname);} else {//General processing Logic return Doresolvedependency (descriptor, Descriptor.getdependencytype (), Beanname, Autowiredbeannames, TypeConverter);}} Protected Object doresolvedependency (dependencydescriptor descriptor, class<?> type, String beanname,set< String> autowiredbeannames, TypeConverter TypeConverter) throws beansexception {/* * to support new annotations in spring @value */object Value = Getautowirecandidateresolver (). Getsuggestedvalue (descriptor); if (value! = null) {if (value instanceof String) { String Strval = Resolveembeddedvalue ((String) value); beandefinition BD = (beanname! = null && conTainsbean (beanname)? Getmergedbeandefinition (Beanname): null); value = Evaluatebeandefinitionstring (Strval, BD);} TypeConverter converter = (TypeConverter! = null? Typeconverter:gettypeconverter ()); return (Descriptor.getfield ()! = Nu ll? converter.convertifnecessary (value, type, Descriptor.getfield ()): Converter.convertifnecessary (value, type, Descriptor.getmethodparameter ()));} If the parser does not parse successfully, you need to consider various cases//attributes are array type if (Type.isarray ()) {class<?> ComponentType = Type.getcomponenttype ();// The matching bean,//return value of all types found in beanfactory based on the property type is: key= matching beanname,value=beanname corresponding instantiated bean (returned by Getbean (Beanname)) Map <string, object> Matchingbeans = Findautowirecandidates (Beanname, ComponentType, descriptor); if ( Matchingbeans.isempty ()) {///If the Autowire require property is true and the match found is empty then only exception if (descriptor.isrequired ()) { Raisenosuchbeandefinitionexception (ComponentType, "array of" + componenttype.getname (), descriptor);} return null;} if (autowiredbeannames! = null) {Autowiredbeannames.addall (matchingbeans.keyset());} TypeConverter converter = (TypeConverter! = null? Typeconverter:gettypeconverter ());//Convert the value of the bean to the corresponding type type return via the converter Converter.convertifnecessary (Matchingbeans.values (), type);} property is Collection type else if (Collection.class.isAssignableFrom (type) && type.isinterface ()) {class<?> ElementType = Descriptor.getcollectiontype (); if (ElementType = = null) {if (descriptor.isrequired ()) {throw new Fatalbeanexception ("No element type declared for collection [" + type.getname () + "]");} return null;} map<string, object> Matchingbeans = Findautowirecandidates (Beanname, ElementType, descriptor); if ( Matchingbeans.isempty ()) {if (descriptor.isrequired ()) {raisenosuchbeandefinitionexception (ElementType, " Collection of "+ Elementtype.getname (), descriptor);} return null;} if (autowiredbeannames! = null) {Autowiredbeannames.addall (Matchingbeans.keyset ());} TypeConverter converter = (TypeConverter! = null? Typeconverter:gettypeconverter ()); return Converter.convertifnecessary (MatchinGbeans.values (), type);} property is the Map type else if (Map.class.isAssignableFrom (type) && type.isinterface ()) {class<?> KeyType = Descriptor.getmapkeytype (); if (KeyType = = NULL | |! String.class.isAssignableFrom (KeyType)) {if (descriptor.isrequired ()) {throw new Fatalbeanexception ("Key type [" + KeyType + "] of Map [" + type.getname () + "] must is assignable to [java.lang.String]");} return null;} class<?> ValueType = Descriptor.getmapvaluetype (), if (ValueType = = null) {if (descriptor.isrequired ()) {throw new F Atalbeanexception ("No value type declared for map [" + type.getname () + "]");} return null;} map<string, object> Matchingbeans = Findautowirecandidates (Beanname, ValueType, descriptor); if ( Matchingbeans.isempty ()) {if (descriptor.isrequired ()) {raisenosuchbeandefinitionexception (ValueType, "map with Value type "+ valuetype.getname (), descriptor);} return null;} if (autowiredbeannames! = null) {Autowiredbeannames.addall (Matchingbeans.keyset ());} return Matchingbeans;} else {map<string, object> Matchingbeans = findautowirecandidates (beanname, type, descriptor); Matchingbeans.isempty ()) {if (descriptor.isrequired ()) {raisenosuchbeandefinitionexception (Type, "", descriptor);} return null;} if (Matchingbeans.size () > 1) {String primarybeanname = determineprimarycandidate (Matchingbeans, descriptor); Primarybeanname = = null) {throw new Nouniquebeandefinitionexception (type, matchingbeans.keyset ());} if (autowiredbeannames! = null) {Autowiredbeannames.add (primarybeanname);} Return Matchingbeans.get (primarybeanname);} We have exactly one match. map.entry<string, object> Entry = Matchingbeans.entryset (). iterator (). Next (); if (autowiredbeannames! = null) { Autowiredbeannames.add (Entry.getkey ());} You have determined that there is only one match return Entry.getvalue ();}}

When looking for a type of matching execution order, the man tries to parse with the parser, if the parser does not parse successfully, the default parser may not have done any processing, or a custom parser has been used.

Although the different types of processing are inconsistent, but the approximate idea is similar, so the function is only an array of types are commented in detail.

3.applyPropertyValues

The program runs here, it has completed the acquisition of all injected properties, but the obtained properties are in the form of propertyvalues and are not applied to the bean that has already been instantiated, and this is done in applypropertyvalues.

protected void Applypropertyvalues (String beanname, beandefinition mbd, beanwrapper bw, propertyvalues PVs) {if (PVs = = Nu ll | | Pvs.isempty ()) {return;} Mutablepropertyvalues MPVs = null; List<propertyvalue> original;if (system.getsecuritymanager () = null) {if (bw instanceof Beanwrapperimpl) {( BEANWRAPPERIMPL) BW). SetSecurityContext (Getaccesscontrolcontext ());}} if (PVs instanceof mutablepropertyvalues) {MPVs = (mutablepropertyvalues) pvs;// If the value in MPVs has been converted to the corresponding type then it can be set directly into Beanwapper if (mpvs.isconverted ()) {//Shortcut:use the pre-converted values as-is.try { Bw.setpropertyvalues (MPVs); return;} catch (Beansexception ex) {throw new Beancreationexception (Mbd.getresourcedescription (), Beanname, "Error setting Property values ", ex);}} Original = Mpvs.getpropertyvaluelist ();} else {//if PVS is not using the Mutablepropertyvalues encapsulated type, then use the original property directly to get the method original = Arrays.aslist (Pvs.getpropertyvalues ());} TypeConverter converter = Getcustomtypeconverter (); if (converter = = null) {converter = bw;} Get the corresponding parser BeandefInitionvalueresolver valueresolver = new Beandefinitionvalueresolver (this, Beanname, MBD, Converter);//Create a deep cop Y, resolving any references for values. list<propertyvalue> deepcopy = new arraylist<propertyvalue> (Original.size ()); Boolean resolveNecessary = false;//Traversal property, converts the property to the corresponding property of the corresponding class for the type for (PropertyValue pv:original) {if (pv.isconverted ()) {Deepcopy.add (PV);} else {String propertyname = Pv.getname (); Object originalvalue = Pv.getvalue (); Object resolvedvalue = Valueresolver.resolvevalueifnecessary (PV, originalvalue); Object Convertedvalue = Resolvedvalue;boolean Convertible = Bw.iswritableproperty (PropertyName) &&! Propertyaccessorutils.isnestedorindexedproperty (PropertyName); if (convertible) {Convertedvalue = Convertforproperty (Resolvedvalue, PropertyName, BW, converter);} Possibly store converted value in merged beans definition,//in order to avoid re-conversion for every created Bean inst Ance.if (Resolvedvalue = = OriginalValue) {if (convertible) {Pv.setconvErtedvalue (Convertedvalue);} Deepcopy.add (PV);} else if (convertible && originalvalue instanceof Typedstringvalue &&! ( (Typedstringvalue) originalvalue). IsDynamic () &&! (Convertedvalue instanceof Collection | | Objectutils.isarray (Convertedvalue)) {Pv.setconvertedvalue (convertedvalue);d Eepcopy.add (PV);} else {resolvenecessary = True;deepcopy.add (new PropertyValue (PV, Convertedvalue));}}} if (MPVs! = null &&!resolvenecessary) {mpvs.setconverted ();} Set our (possibly massaged) deep Copy.try {bw.setpropertyvalues (new mutablepropertyvalues (deepcopy));} catch (Beansexception ex) {throw new Beancreationexception (Mbd.getresourcedescription (), Beanname, "Error setting Property values ", ex);}}


Bean loading (10) attribute injection

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.