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

  • storageBeanDefinitionHolderObject that stores the mapping between the Bean’s name and aliasBeanDefinitionAccess mode of
  • AnnotatedElementThis is an annotation for the Java reflection package that developers can use to manipulate annotations. As usualgetAnnotation(),getAnnotations(),isAnnotationPresent()Etc.
  • allowCaching, whether caching is allowed
  • isFactoryMethodUniqueIs the factory method unique
  • targetType, utility classes related to Java generics
  • resolvedTargetType, the Class object held by the current Class
  • factoryMethodToIntrospect, cache factory method
  • ExecutableCache parsed constructors or methods. Executable is the parent of Method and Construct
  • constructorArgumentsResolved, a Boolean value indicating whether the constructor has been resolved
  • resolvedConstructorArguments, caches fully parsed constructor arguments
  • postProcessed, whether be MergedBeanDefinitionPostProcessor processing
  • beforeInstantiationResolvedThe post-processor before instantiation has been started
  • externallyManagedInitMethods, the callback function at initialization
  • externallyManagedDestroyMethodsDestruction-time callback function
  • constructorArgumentLockandpostProcessingLock, 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.