BeanDefinition
As you can see from my last article, BeanDefinition defines roughly what information a Bean needs. It defines getter and setter methods for that information. As an interface layer, it is not responsible for defining specific parameters. AbstractBeanDefinition implements this interface, which provides the basic capabilities required by a BeanDefinition. If you need to extend the functionality, you can extend the class and add more. Today we’ll look at three subclasses of AbstractBeanDefinition:
- RootBeanDefinition
- ChildBeanDefinition
- GenericBeanDefinition
RootBeanDefinition
Starting with Spring2.5, RootBeanDefinition is only used as a BeanDefinition view at runtime. GenericBeanDefinition is recommended if you need to programmatically define a BeanDefinition. Spring explains that the advantage of GenericBeanDefinition is that it allows parent dependencies to be defined dynamically, rather than a role that is “hard-coded” to define a BeanDefinition. That is, the general form of a bean exists in the standard form of a GenericBeanDefinition, which is converted to a RootBeanDefinition at a given moment
RootBeanDefinition characteristics
- storage
BeanDefinitionHolder
Object that stores the mapping between the Bean’s name and aliasBeanDefinition
Access mode of AnnotatedElement
This is an annotation for the Java reflection package that developers can use to manipulate annotations. As usualgetAnnotation()
,getAnnotations()
,isAnnotationPresent()
Etc.allowCaching
, whether caching is allowedisFactoryMethodUnique
Is the factory method uniquetargetType
, utility classes related to Java genericsresolvedTargetType
, the Class object held by the current ClassfactoryMethodToIntrospect
, cache factory methodExecutable
Cache parsed constructors or methods. Executable is the parent of Method and ConstructconstructorArgumentsResolved
, a Boolean value indicating whether the constructor has been resolvedresolvedConstructorArguments
, caches fully parsed constructor argumentspostProcessed
, whether be MergedBeanDefinitionPostProcessor processingbeforeInstantiationResolved
The post-processor before instantiation has been startedexternallyManagedInitMethods
, the callback function at initializationexternallyManagedDestroyMethods
Destruction-time callback functionconstructorArgumentLock
andpostProcessingLock
, object lock, interested in their own in-depth. I’m not going to elaborate here
In addition, the RootBeanDefinition cannot perform the setParentName() operation. You can see that it stores a lot of information about annotations and reflection, which may be used for reflection at some point.
Demo
Instantiate a RootBeanDefinition through Java code
Root
public class Root {
private String name;
private String description;
private boolean isRoot;
public Root(a) {}/** * constructor *@paramName The index of the name is 0 *@paramDescription The index corresponding to the description is 1 *@paramIsRoot is the parent of BeanDefinition and the corresponding index is 2 */
public Root(String name, String description, Boolean isRoot) {
this.name = name;
this.description = description;
this.isRoot = isRoot;
}
@Override
public String toString(a) {
return "Root{" +
"name='" + name + '\' ' +
", description='" + description + '\' ' +
", isRoot=" + isRoot +
'} ';
}
public String getName(a) {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription(a) {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean getIsRoot(a) {
return isRoot;
}
public void setIsRoot(boolean root) { isRoot = root; }}Copy the code
Child
package com.xjm.model;
/ * * *@author jaymin
* 2020/11/29 14:21
*/
public class Child {
private String name;
private String description;
private boolean isRoot;
private String parentName;
public Child(String name, String description, boolean isRoot, String parentName) {
this.name = name;
this.description = description;
this.isRoot = isRoot;
this.parentName = parentName;
}
public Child(a) {}public String getName(a) {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription(a) {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean getIsRoot(a) {
return isRoot;
}
public void setIsRoot(boolean root) {
isRoot = root;
}
public String getParentName(a) {
return parentName;
}
public void setParentName(String parentName) {
this.parentName = parentName;
}
@Override
public String toString(a) {
return "Child{" +
"name='" + name + '\' ' +
", description='" + description + '\' ' +
", isRoot=" + isRoot +
", parentName='" + parentName + '\' ' +
'} '; }}Copy the code
I’m not going to redefine the object that I defined here because I’m going to reuse it
RootBeanDefinitionDemo
package com.xjm.bean.definition;
import com.xjm.model.Root;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/ * * *@author jaymin<br>
* <p>
* 2020/11/29 13:28
*/
@SuppressWarnings("all")
public class RootBeanDefinitionDemo {
/** * Get RootBeanDefinition ** via constructor injection argument@return* /
public static RootBeanDefinition getRootBeanDefinitionByConstruct(a) {
ConstructorArgumentValues cargs = new ConstructorArgumentValues();
cargs.addIndexedArgumentValue(0."rootA");
cargs.addIndexedArgumentValue(1."This is a RootBeanDefinition");
cargs.addIndexedArgumentValue(2.true);
RootBeanDefinition rootBeanDefinitionA = new RootBeanDefinition(Root.class, cargs, null);
return rootBeanDefinitionA;
}
/** * Returns RootBeanDefinition ** by injecting parameters as setters@return* /
public static RootBeanDefinition getRootBeanDefinitionBySetter(a) {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.addPropertyValue("name"."rootB");
propertyValues.addPropertyValue("description"."This is a RootBeanDefinition");
propertyValues.addPropertyValue("isRoot".true);
RootBeanDefinition rootBeanDefinitionB = new RootBeanDefinition(Root.class, null, propertyValues);
return rootBeanDefinitionB;
}
public static void main(String[] args) {
// 1. Build an empty container
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// create a RootBeanDefinition
RootBeanDefinition rootBeanDefinitionA = getRootBeanDefinitionByConstruct();
RootBeanDefinition rootBeanDefinitionB = getRootBeanDefinitionBySetter();
applicationContext.registerBeanDefinition("rootA", rootBeanDefinitionA);
applicationContext.registerBeanDefinition("rootB", rootBeanDefinitionB);
// There is a point where the constructor of the Root object is called
applicationContext.refresh();
Root rootA = ((Root) applicationContext.getBean("rootA"));
Root rootB = ((Root) applicationContext.getBean("rootB")); System.out.println(rootA.toString()); System.out.println(rootB.toString()); }}Copy the code
ChildBeanDefinition
SetParentName () is supported. The parameter is the name of the parent RootBeanDefinition, and the inheritance relationship is set through the constructor. Spring notes that GenericBeanDefinition can replace ChildBeanDefinition in most cases, so I won’t go into details here, but provide a demo for you to taste.
ChildBeanDefinitionDemo
package com.xjm.bean.definition;
import com.xjm.model.Child;
import com.xjm.model.Root;
import org.springframework.beans.factory.support.ChildBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/ * * *@author jaymin<br>
* <p>
* 2020/11/29 14:20
*/
@SuppressWarnings("all")
public class ChildBeanDefinitionDemo {
public static void main(String[] args) {
// 1. Build an empty container
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
String parentName = "rootB";
String childName = "child";
RootBeanDefinition rootBeanDefinition = RootBeanDefinitionDemo.getRootBeanDefinitionBySetter();
ChildBeanDefinition childBeanDefinition = new ChildBeanDefinition(parentName);
childBeanDefinition.setBeanClass(Child.class);
childBeanDefinition.getPropertyValues().addPropertyValue("parentName", parentName);
childBeanDefinition.getPropertyValues().addPropertyValue("isRoot".false);
/ / register
applicationContext.registerBeanDefinition(parentName, rootBeanDefinition);
applicationContext.registerBeanDefinition(childName, childBeanDefinition);
// Refresh the contextapplicationContext.refresh(); Root root = applicationContext.getBean(Root.class); Child child = (Child) applicationContext.getBean(childName); System.out.println(root.toString()); System.out.println(child.toString()); }}Copy the code
GenericBeanDefinition
SetParentName () provides the setParentName() method, which is setter, by reading the Spring comments, which describes it as follows:
GenericBeanDefinition is a one-stop shop for standard bean definitions. Like any bean definition, it allows you to specify a class and optional constructor parameter and attribute values. In addition, you can flexibly configure content derived from the parent bean definition through the “parentName” property.
GenericBeanDefinitionDemo
package com.xjm.bean.definition;
import com.xjm.model.Child;
import com.xjm.model.Root;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/ * * *@author jaymin
* 2020/11/29 14:57
*/
public class GenericBeanDefinitionDemo {
public static GenericBeanDefinition getRootBeanDefinition(a) {
GenericBeanDefinition rootBeanDefinition = new GenericBeanDefinition();
rootBeanDefinition.setBeanClass(Root.class);
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("name"."root")
.add("description"."I am a rootBeanDefinition")
.add("isRoot".true);
rootBeanDefinition.setPropertyValues(propertyValues);
return rootBeanDefinition;
}
public static GenericBeanDefinition getChildBeanDefinition(a) {
GenericBeanDefinition childBeanDefinition = new GenericBeanDefinition();
childBeanDefinition.setBeanClass(Child.class);
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("parentName"."root");
childBeanDefinition.setParentName("root");
childBeanDefinition.setPropertyValues(propertyValues);
return childBeanDefinition;
}
public static void main(String[] args) {
// 1. Build an empty container
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
GenericBeanDefinition rootBeanDefinition = getRootBeanDefinition();
GenericBeanDefinition childBeanDefinition = getChildBeanDefinition();
applicationContext.registerBeanDefinition("root", rootBeanDefinition);
applicationContext.registerBeanDefinition("child", childBeanDefinition); applicationContext.refresh(); Root root = applicationContext.getBean(Root.class); Child child = applicationContext.getBean(Child.class); System.out.println(root.toString()); System.out.println(child.toString()); }}Copy the code
As you can see, we can do what RootBeanDefinition and RootBeanDefinition can do with just one GenericBeanDefinition. To copy the information of another BeanDefinition, you simply need setParentName(). extensible
Words left to the reader
The Spring source project is very large, but provides a lot of comments, sometimes a lot of light variables, how do we make these things impress us, only practice and thinking. My personal knowledge reserves are not rich enough, can only leave some code, interested friends can follow the implementation of their own, feel the power of Spring. As for the deeper principles, can not be fully explained thoroughly at present. If there is something wrong, please correct it.