1 How to define Beans
The common ways to define beans are:
- by XML, for example:
<bean id= "Dictionaryrelmap" class = " Java.util.HashMap "/>
- use annotations such as @component on class with annotations such as
@ Component public class xxxservicer{...}
- by means of @bean under the @configuration class, for example
@Configuration public class xxxconfiguration{@Bean public Mybean Mybean () { return New Mybean (); }}
Although the three different ways to define beans, the corresponding processing details are different, but from a large logical point of view, are the same. The main process, such as: The problem is to find the way to define the bean, then generate beandefinition to register in the spring context, and spring automatically creates an instance of the bean.
2 beandefinition
Beandefinition is an interface that describes a bean instance, such as Singleton or prototype, what the value of the property is, what the constructor's arguments are, and so on. Simply put, with a beandefinition we can complete a bean instantiation. Beandefinition and its main subclasses:
Here's a brief look at each sub-class:
- Rootbeandefinition and Childbeandefinition: These 2 beandefinition are relative relations, since spring 2.5 came out, has been replaced by Genericbeandefinition. Because it forces us to be aware of their relationship when writing code.
- Genericbeandefinition: Hard coding is required compared to rootbeandefinition and childbeandefinition at the time of definition. The genericbeandefinition has the advantage of being able to dynamically set the parent for genericbeandefinition.
- Annotatedbeandefinition: The name is known to be used to read the definition bean through annotations.
3 defining beans through XML files
Defining a bean through XML is the first way to define a bean in spring. So, how to parse the XML tag into beandefinition (), the entry is in org.springframework.beans.factory.xml.XmlBeanDefinitionReader
this class, but the actual work is in org.springframework.beans.factory.xml.BeanDefinitionParserDelegate
. The code is a lot, but the actual logic is simple, which is to parse the spring-defined <bean> <property> tags. I've written an article about how to customize the spring label, and then sign in to spring--the portal
4 Loading beans with spring-supported annotations such as @component
If you want to @Component
define a bean using such annotations, a precondition is: Yes <context:component-scan/>
or no @ComponentScan
annotation. But these 2 ways still have a little bit of a difference:
4.1 <context:component-scan/>
Because <context:component-scan/>
it is an XML tag, it is parsing the XML, generating the class org.springframework.context.annotation.ComponentScanBeanDefinitionParser
, the key code:
@Override PublicBeandefinition Parse (element element, ParserContext ParserContext) {//Get Base-package TagsString Basepackage =Element.getattribute (Base_package_attribute); Basepackage=Parsercontext.getreadercontext (). Getenvironment (). Resolveplaceholders (Basepackage); String[] Basepackages=Stringutils.tokenizetostringarray (Basepackage, configurableapplicationcontext.config_location_delimiters); //the actual processing class is ClasspathbeandefinitionscannerClasspathbeandefinitionscanner scanner =Configurescanner (parsercontext, Element); //Scan all classes under Basepackage, if you have @component and other tags are registered in springSet<beandefinitionholder> beandefinitions =Scanner.doscan (basepackages); Registercomponents (Parsercontext.getreadercontext (), beandefinitions, Element); return NULL;}
4.2 @ComponentScan
annotation corresponds to the generated class is org.springframework.context.annotation.ComponentScanAnnotationParser
actually the last actual work or ClassPathBeanDefinitionScanner
this. The ComponentScanAnnotationParser
generation of classes is accompanied by @Configuration
this annotation process (meaning @ComponentScan
must and @Configuration
used together). And @Configuration
the deal is actually org.springframework.context.annotation.ConfigurationClassPostProcessor
. Does it feel a little bit around.
In fact, in the simple case, when the processing @Configuration
of the discovery of @ComponentScan
annotations, will be generated ComponentScanAnnotationParser
to scan @component annotations
4.3 classpathbeandefinitionscanner
As mentioned above, regardless of the annotation or the way of the label, the end will be handed over to ClassPathBeanDefinitionScanner
this class to deal with, this class does is 1. Scan all classes under Basepackage, if there are annotations such as @component, read @component related properties, generate ScannedGenericBeanDefinition
, register to spring.
5 by @bean Way
Said before the @componentscan is in the @configuration process of a link, since the @bean annotation also must be used with @configuration, then the @bean processing is also in the @configuration, In fact, the final is ConfigurationClassBeanDefinitionReader
to this class to deal with, the key code:
Private voidLoadbeandefinitionsforconfigurationclass (ConfigurationClass configclass, Trackedconditionevaluator trackedCon Ditionevaluator) {//If you are defined by @import annotations, you need to register yourself in spring if(configclass.isimported ()) {Registerbeandefinitionforimportedconfigurationclass (configclass); } //This is the @bean of the processing method. for(Beanmethod beanMethod:configClass.getBeanMethods ()) {Loadbeandefinitionsforbeanmethod (Beanmethod); } //processing @importresource, inside parsing XML is the Xmlbeandefinitionreader of parsing XML mentioned aboveloadbeandefinitionsfromimportedresources (Configclass.getimportedresources ()); Loadbeandefinitionsfromregistrars (Configclass.getimportbeandefinitionregistrars ());}
6 instantiation of the Beandefinition
The previous section said how to convert different definitions of beans to beandefinition to join spring (to be sure to remain in the Beanfactory Beandefinitionmap), The instance is in the final phase of ApplicationContext, and the key code is in Defaultlistablebeanfactory
@Override Public voidPreinstantiatesingletons ()throwsbeansexception { for(String beanname:beannames) {rootbeandefinition bd=getmergedlocalbeandefinition (beanname); if(!bd.isabstract () && Bd.issingleton () &&!Bd.islazyinit ()) { if(Isfactorybean (beanname)) {FinalFactorybean<?> factory = (factorybean<?>) Getbean (Factory_bean_prefix +beanname); BooleanIseagerinit; if(System.getsecuritymanager ()! =NULL&& FactoryinstanceofSmartfactorybean) {Iseagerinit= Accesscontroller.doprivileged (NewPrivilegedaction<boolean>() {@Override PublicBoolean Run () {return((smartfactorybean<?>). Factory). Iseagerinit (); }}, Getaccesscontrolcontext ()); } Else{iseagerinit= (FactoryinstanceofSmartfactorybean &&((Smartfactorybean<?>) factory). Iseagerinit ()); } if(iseagerinit) {Getbean (beanname); } } Else{Getbean (beanname); } } }
}
By Getbean the last last instance of the code, in Abstractautowirecapablebeanfactory
protectedObject Initializebean (FinalString Beanname,FinalObject Bean, rootbeandefinition mbd) { //Handling Xxaware Interfaces if(System.getsecuritymanager ()! =NULL) {accesscontroller.doprivileged (NewPrivilegedaction<object>() {@Override PublicObject Run () {invokeawaremethods (beanname, Bean); return NULL; }}, Getaccesscontrolcontext ()); } Else{invokeawaremethods (beanname, Bean); } Object Wrappedbean=Bean; if(mbd = =NULL|| !mbd.issynthetic ()) { //Call Beanpostprocessors#postprocessbeforeinitializationWrappedbean =applybeanpostprocessorsbeforeinitialization (Wrappedbean, beanname); } Try { //Initialize, first determine whether it is Initializingbean,invokeinitmethods (Beanname, Wrappedbean, mbd); } Catch(Throwable ex) {Throw Newbeancreationexception ((mbd!=NULL? Mbd.getresourcedescription ():NULL), Beanname,"Invocation of Init method failed", ex); } if(mbd = =NULL|| !mbd.issynthetic ()) { //Call Beanpostprocessors#postprocessafterinitializationWrappedbean =applybeanpostprocessorsafterinitialization (Wrappedbean, beanname); } returnWrappedbean;}
As you can see from the above initialization, Initializebean and Beanpostprocessors call order
7 Summary
Based on the analysis, the spring load bean is the same as the big idea, first read the relevant information to generate Beandefinition, and then initialize the bean through beandefinition. If you know the above routines, you can clearly see how to customize XML tags or custom annotations to inject beans into spring.
A brief analysis of spring's multiple load bean methods