Accumulate over a long period, constant dripping wears away a stone 😄

BeanDefinition

In the Spring container, we generally use Bean by Bean. How can we define a Bean in Spring?

  • The label

  • @ Bean annotations

  • @ Component (@ Service, @ Controller)

The other thing is you can use BeanDefinition.

For example, we can define a Bean by defining a BeanDefinition object:

Add the spring-context dependency to the project as follows:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.6. RELEASE</version>
</dependency>
Copy the code

Then create the User class

public class User {
    private Long id;
    private String name;

    public Long getId(a) {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName(a) {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void init(a){
		System.out.println("Initialize"); }}Copy the code
public static void main(String[] args) {
        // Define a BeanDefinition
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        // The type of the current Bean object
        beanDefinition.setBeanClass(User.class);
        // Register BeanDefinition with BeanFactory
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerBeanDefinition("user", beanDefinition);
        / / get a Bean
        System.out.println(beanFactory.getBean("user")); } result: com.gongj.entity.User@70177ecdCopy the code

We can also set other properties of a Bean through BeanDefinition

// Set the scope
beanDefinition.setScope("prototype");
// Set the initialization method
beanDefinition.setInitMethodName("init");
// Set the autowiring modelbeanDefinition.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE); Result: initialize com.gongj.entity.User@1e88b3cCopy the code

Note: init() is required for the User class.

Anyway, beans defined by @beans, @Component, etc., will eventually be resolved as BeanDefinition objects. To understand BeanDefinition, we start with the inheritance relationship of beandefinitions:

You can see that BeanDefinition is an interface that inherits from the BeanMetadataElement and AttributeAccessor interfaces.

  • AttributeAccessor: Interface that defines a common protocol for attaching and accessing metadata, which can be any object. The concrete implementation isAttributeAccessorSupport, the use ofLinkedHashMapStore it.
public interface AttributeAccessor {
 
	// Set the value of the property (name unique)
	void setAttribute(String name, Object value);
 
	// Returns the value of the specified attribute name, or null if none is present
	Object getAttribute(String name);
 
	// Remove the attribute of the specified name, or return null if it does not exist
	Object removeAttribute(String name);
 
      // Checks whether the specified attribute name exists
	boolean hasAttribute(String name);
 
	// Returns the names of all attributes
	String[] attributeNames();
}
Copy the code
  • BeanMetadataElement: This interface has only one method, getSource, which returns the Bean’s origin.

These are the two interfaces that BeanDefinition inherits. Now let’s look at the BeanDefinition itself:

public interface BeanDefinition extends AttributeAccessor.BeanMetadataElement {

// Singleton beans are still prototype beans
 String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
 String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

/ / Bean role
 int ROLE_APPLICATION = 0;  // User-defined Bean
 int ROLE_SUPPORT = 1;  // Beans from the configuration file
 int ROLE_INFRASTRUCTURE = 2;//Spring internal Bean


      
 void setParentName(@Nullable String parentName);
 @Nullable
 String getParentName(a);

< Bean Class ="">
 void setBeanClassName(@Nullable String beanClassName);
 @Nullable
 String getBeanClassName(a);

// Configure/get the < Bean scope=""> configuration in the Bean scope XML.
 void setScope(@Nullable String scope);
 @Nullable
 String getScope(a);

// Configure/get Bean lazy loading (default is immediately loaded)

      
 void setLazyInit(boolean lazyInit);
 boolean isLazyInit(a);

< Bean depends-on="">
 void setDependsOn(@Nullable String... dependsOn);
 @Nullable
 String[] getDependsOn();

< Bean autowire-candidate=""> in XML
 void setAutowireCandidate(boolean autowireCandidate);
 boolean isAutowireCandidate(a);

// If more than one injectable bean is found, select the bean marked as Primary/get when
< Bean primary="">
 void setPrimary(boolean primary);
 boolean isPrimary(a);


      
 void setFactoryBeanName(@Nullable String factoryBeanName);
 @Nullable
 String getFactoryBeanName(a);

// Configure/get the name of a FactoryMethod, which can be a method of an instance (used with a factoryBean)
// It can also be static. 
      
 void setFactoryMethodName(@Nullable String factoryMethodName);
 @Nullable
 String getFactoryMethodName(a);

// Returns the parameter value of the Bean constructor
 ConstructorArgumentValues getConstructorArgumentValues(a);

/ / determine whether getConstructorArgumentValues null objects.
 default boolean hasConstructorArgumentValues(a) {
  return! getConstructorArgumentValues().isEmpty(); }// Get a collection of common attributes
 MutablePropertyValues getPropertyValues(a);

// Check whether getPropertyValues is an empty object
 default boolean hasPropertyValues(a) {
  return! getPropertyValues().isEmpty(); }< Bean init-method="">
 void setInitMethodName(@Nullable String initMethodName);
 @Nullable
 String getInitMethodName(a);

< Bean destroy-method="">
 void setDestroyMethodName(@Nullable String destroyMethodName);
 @Nullable
 String getDestroyMethodName(a);

// Configure/get the role of the Bean
 void setRole(int role);
 int getRole(a);

// Configure/get a description of the Bean
 void setDescription(@Nullable String description);
 @Nullable
 String getDescription(a);

// Used to parse various information about a Bean's type, such as generics
 ResolvableType getResolvableType(a);

// Whether it is a singleton
 boolean isSingleton(a);

// Whether it is a prototype
 boolean isPrototype(a);

// Whether to abstract 
      
 boolean isAbstract(a);

// Returns the resource description that defines the Bean
 @Nullable
 String getResourceDescription(a);

This method can be used to return the original BeanDefinition if the current BeanDefinition is a proxy object
 @Nullable
 BeanDefinition getOriginatingBeanDefinition(a);
}
Copy the code

BeanDefinition implementation class

BeanDefinition is an interface that has multiple implementation classes that describe different types of beans. There are roughly two types:

  • Abstract implementation:AbstractBeanDefinition
  • The child interface:AnnotatedBeanDefinition

Let’s look at another inheritance diagram:Some extraneous inheritance relationships were removed, resulting in the image above.

Abstract implementation: AbstractBeanDefinition

AbstractBeanDefinition is an abstract class. AbstractBeanDefinition only defines a series of get/set methods, but does not provide corresponding attributes. AbstractBeanDefinition defines all attributes. This abstract class has three subclasses: GenericBeanDefinition, RootBeanDefinition, and ChildBeanDefinition. Let’s start by looking at some methods and properties of AbstractBeanDefinition itself.

public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
		implements BeanDefinition.Cloneable {

    // Constant of the default scope name: equivalent to a singleton
    public static final String SCOPE_DEFAULT = "";

    // Some constants for autowiring
    // autowireMode = 0, default, Autowiring is not enabled.
    // The autowire attribute of the bean tag has a value of no
    You need to manually specify the dependency injection object configuration property tag or constructor-arg tag in XML
    // 2. Use the @autoWired annotation. AutowireMode is also 0
    public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;
    //autowireMode = 1, does a dependency lookup based on the name of the set method as the Bean name (drop the set and try to lower the first letter to lowercase), and sets the object to the parameters of the set method
    // The autowire property value of the bean tag is set to byName
    public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
    //autowireMode = 2, depending on the type of the parameter of the set method as the Bean type, and sets the object to the parameter of the set method
    // The autowire property value of the bean tag is set to byType
    public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
    //autowireMode = 3, constructor injection
    // The autowire property value of the bean tag is configured to constructor
    public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
    // indicates that Spring3.0 is deprecated for autowiring through the Bean's class.
    // The autowire property value of the bean label is configured to autodetect
    @Deprecated
    public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;

    // Check whether a dependency is valid. In this class, dependency checking is not performed by default
    // Do not check
    public static final int DEPENDENCY_CHECK_NONE = 0;
    // Perform dependency checking on object references
    public static final int DEPENDENCY_CHECK_OBJECTS = 1;
    // Perform dependency checking on "simple" properties
    public static final int DEPENDENCY_CHECK_SIMPLE = 2;
    // Perform a dependency check on all attributes
    public static final int DEPENDENCY_CHECK_ALL = 3;

    // If the Bean does not specify a destruction method, the container should try to infer the Bean's destruction method name,
    // Currently, the presumed name of the destruction method is close or shutdown
    public static final String INFER_METHOD = "(inferred)";

    // The fully qualified name of the Bean's class object or class
    @Nullable
    private volatile Object beanClass;

    // The default scope is a singleton corresponding to the bean property scope
    //@Scope
    @Nullable
    private String scope = SCOPE_DEFAULT;

    // Whether it is abstract, corresponding to bean attribute abstract
    private boolean abstractFlag = false;

    // If the bean is lazy, the corresponding property is lazy-init, which is not lazy by default
    //@Lazy
    @Nullable
    private Boolean lazyInit;

    // Auto-injection mode, corresponding to the bean property autowire, does not auto-assemble by default
    private int autowireMode = AUTOWIRE_NO;

    // Whether to perform the dependency check. By default, the dependency check is not performed
    private int dependencyCheck = DEPENDENCY_CHECK_NONE;

    $dependsOn () $dependsOn () $dependsOn () $dependsOn ()
    // The corresponding bean attribute depends on
    //@DependsOn
    @Nullable
    private String[] dependsOn;

    /** * the autowire-candidate property is set to false so that the bean will not be considered as a candidate for the autowire of other beans when the container looks for autowire objects. * But the bean itself can still use autowiring to inject the */ of other beans
    private boolean autowireCandidate = true;

    /** * If more than one bean candidate is present during autowiring, it will be preferred, corresponding to the bean property primary, which is not preferred by default *@Primary* /
    private boolean primary = false;
    /** * for Qualifier, The child element is qualifier <bean><qualifier></qualifier></bean> * If there are multiple beans of the same type in the container, then we can use the qualifier property to set the bean to load with the specified bean name *@Qualifier* /
    private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>();

    // Java8 functional interface, one of the ways to create bean instances
    @Nullable
    privateSupplier<? > instanceSupplier;// Whether access to non-public methods and attributes is allowed. The default is true
    private boolean nonPublicAccessAllowed = true;

    /** * Whether to parse the constructor in a loose mode, default is true, * if false, in the following cases * interface ITest{} * class ITestImpl implements ITest{}; * Class Main {* Main(ITestI) {} * Main(ITestImpl I) {} *} * throws an exception because Spring cannot locate exactly which constructor Settings */
    private boolean lenientConstructorResolution = true;

    // The factory class name, corresponding to the bean property factory-bean
    @Nullable
    private String factoryBeanName;

    // The factory method name, corresponding to the bean property factory-method
    @Nullable
    private String factoryMethodName;

    // Record the constructor injection property corresponding to the bean property constructor-arg
    @Nullable
    private ConstructorArgumentValues constructorArgumentValues;

    // The name of the Bean property and its corresponding value. Constructors are not stored here, only dependencies injected through setters are stored here
    @Nullable
    private MutablePropertyValues propertyValues;

    // The holder of the method override, which records the lookup-method, appet-method element @lookup
    private MethodOverrides methodOverrides = new MethodOverrides();

    // Initialize the method corresponding to the bean property init-method
    @Nullable
    private String initMethodName;

    // Destroy method corresponding to bean property destroy-method
    @Nullable
    private String destroyMethodName;

    // Whether to execute init-method. Default is true
    private boolean enforceInitMethod = true;

    // Whether to destroy-method. The default is true
    private boolean enforceDestroyMethod = true;

    // Is user-defined rather than application-defined, true when AOP is created
    private boolean synthetic = false;

    // The role of the Bean for the user to define the Bean
    private int role = BeanDefinition.ROLE_APPLICATION;

    // Describes the Bean
    @Nullable
    private String description;

    // Resource defined by this bean
    @Nullable
    private Resource resource;
    / /...
}
Copy the code

RootBeanDefinition

This is one of the most common implementation classes that Spirng creates beans based on RootBeanDefinition! RootBeanDefinition inherits AbstractBeanDefinition, AbstractBeanDefinition extends some additional functionality, and RootBeanDefinition has no parent BeanDefinition.

public class RootBeanDefinition extends AbstractBeanDefinition {

	// BeanDefinitionHolder Stores Bean names, aliases, and beanDefinitions
	@Nullable
	private BeanDefinitionHolder decoratedDefinition;

	// AnnotatedElement is an interface to the Java reflection package that allows you to view annotation information for beans
	@Nullable
	private AnnotatedElement qualifiedElement;

	// Determines when BeanDefinition needs to be remerged
	volatile boolean stale;

	// Cache is allowed
	boolean allowCaching = true;

	// Is the factory method unique
	boolean isFactoryMethodUnique = false;

	// Encapsulates java.lang.reflect.Type to provide generic-related operations
	@Nullable
	volatile ResolvableType targetType;

	// Used to cache classes identified in the given bean definition
	// Indicates which class information is stored by RootBeanDefinition
	@Nullable
	volatileClass<? > resolvedTargetType;// If the bean is a FactoryBean, it is used for caching
	@Nullable
	volatile Boolean isFactoryBean;

	// The return type used to cache the generic type factory method
	@Nullable
	volatile ResolvableType factoryMethodReturnType;

	// A unique factory method for caching
	@Nullable
	volatile Method factoryMethodToIntrospect;

	// Public locks for the following four constructor fields
	final Object constructorArgumentLock = new Object();
	// Use it to cache parsed constructors or factory methods
	@Nullable
	Executable resolvedConstructorOrFactoryMethod;
	// Mark the constructor argument as resolved
	boolean constructorArgumentsResolved = false;
	// Used to cache fully parsed constructor arguments
	@Nullable
	Object[] resolvedConstructorArguments;
	// The constructor argument is used for the cache section
	@Nullable
	Object[] preparedConstructorArguments;

	// Generic locks for the following two post-processing fields
	final Object postProcessingLock = new Object();

	/ / this suggests MergedBeanDefinitionPostProcessor has been applied
	boolean postProcessed = false;

	// Indicates that a pre-instantiated post-processor has been started
	@Nullable
	volatile Boolean beforeInstantiationResolved;

	The actual cache types are Constructor, Field, and Method
	@Nullable
	private Set<Member> externallyManagedConfigMembers;

	// The init callback function name afterPropertiesSet in the InitializingBean is logged here for the lifecycle callback
	@Nullable
	private Set<String> externallyManagedInitMethods;

	// DisposableBean's destroy callback name destroy will be recorded here for the lifecycle callback
	@Nullable
	private Set<String> externallyManagedDestroyMethods;

    //=========== post a method
	RootBeanDefiniiton clearly means no parent BeanDefinition
	@Override
	public String getParentName(a) {
		return null;
	}
 // Can't set yet
	@Override
	public void setParentName(@Nullable String parentName) {
		if(parentName ! =null) {
			throw new IllegalArgumentException("Root bean cannot be changed into a child bean with parent reference"); }}}Copy the code

practice

Reuse the User class we started with, but add the toString method to it.

public static void main(String[] args) {
          / / container
		DefaultListableBeanFactory context = new DefaultListableBeanFactory();
		AbstractBeanDefinition is already mentioned in its parent class AbstractBeanDefinition
		MutablePropertyValues mpvs = new MutablePropertyValues();
		mpvs.add("id".4L);
		mpvs.add("name"."gongj");
		//BeanDefinition
		RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(User.class,null,mpvs);
		// Register with the Spring container
		context.registerBeanDefinition("user",rootBeanDefinition);
		User user = (User)context.getBean("user"); System.out.println(user); } result: User{id=4, name='gongj'}
Copy the code

ChildBeanDefinition

This class inherits from AbstractBeanDefinition. It is equivalent to a subclass and cannot exist alone. It must rely on a parent BeanDetintion. When constructing ChildBeanDefinition, pass the name of the parent BeanDetintion through the constructor or set the parent name through setParentName. It can inherit method parameters and attribute values from the parent class, override methods of the parent class, and add new attributes or methods.

Starting with Spring 2.5, the preferred method for programmatically registering Bean definitions is GenericBeanDefinition, which can effectively substitute for most partial use of ChildBeanDefinition.

practice

Create a New Person class that adds an Address attribute to the User class.

public class Person {

	private Long id;
	private String name;
	private String address;

	public Long getId(a) {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName(a) {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAddress(a) {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	@Override
	public String toString(a) {
		return "Person{" +
				"id=" + id +
				", name='" + name + '\' ' +
				", address='" + address + '\' ' +
				'} '; }}Copy the code

Start the

public static void main(String[] args) {
		/ / container
		DefaultListableBeanFactory context = new DefaultListableBeanFactory();
		AbstractBeanDefinition // The set of common attributes is already mentioned in its parent class
		MutablePropertyValues mpvs = new MutablePropertyValues();
		mpvs.add("id".4L);
		mpvs.add("name"."gongj");
		//BeanDefinition
		RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(User.class,null,mpvs);
		// Register with the Spring container
		context.registerBeanDefinition("user",rootBeanDefinition);

		/ / ChildBeanDefinition began
		MutablePropertyValues childValues = new MutablePropertyValues();
		childValues.add("address"."Shanghai");
		// Pass the name of the parent BeanDetintion through the constructor
		ChildBeanDefinition childBeanDefinition  = new ChildBeanDefinition("user", Person.class,null,childValues);
		/ / register
		context.registerBeanDefinition("person", childBeanDefinition);

		User user = context.getBean(User.class);
		Person person = context.getBean(Person.class);
		System.out.println("user = " + user);
		System.out.println("person = "+ person); } result: user = user {id=4, name='gongj'}
person = Person{id=4, name='gongj', address='Shanghai'}
Copy the code

GenericBeanDefinition

GenericBeanDefinition is a bean file configuration property definition class that has been added since Spring2.5 and is a one-stop service class. GenericBeanDefinition can dynamically set the parent Bean and has both RootBeanDefinition and ChildBeanDefinition functions.

The implementation of GenericBeanDefinition is relatively simple. AbstractBeanDefinition only adds the function of parentName on the basis of AbstractBeanDefinition, and the other implementations are in the parent class AbstractBeanDefinition. Note: If you are an XML configuration, all attributes will be parsed and encapsulated into an instance of type GenericBeanDefinition, which will be parsed over time.

practice

public static void main(String[] args) {
	/ / container
	DefaultListableBeanFactory ctx = new DefaultListableBeanFactory();
	AbstractBeanDefinition // The set of common attributes is already mentioned in its parent class
	MutablePropertyValues mpvs = new MutablePropertyValues();
	mpvs.add("id".4L);
	mpvs.add("name"."gongj");
	GenericBeanDefinition parentGenericBeanDefinition = new GenericBeanDefinition();
	parentGenericBeanDefinition.setBeanClass(User.class);
	parentGenericBeanDefinition.setPropertyValues(mpvs);
	// Register with the Spring container
	ctx.registerBeanDefinition("user",parentGenericBeanDefinition);

	GenericBeanDefinition childGenericBeanDefinition = new GenericBeanDefinition();
	// Set the parent BeanDefinition name
	childGenericBeanDefinition.setParentName("user");
	childGenericBeanDefinition.setBeanClass(Person.class);
	childGenericBeanDefinition.getPropertyValues().add("address"."Shanghai");
	// Register with the Spring container
	ctx.registerBeanDefinition("person", childGenericBeanDefinition);
	User user = ctx.getBean(User.class);
	Person person = ctx.getBean(Person.class);
	System.out.println("user = " + user);
	System.out.println("person = "+ person); } result: user = user {id=4, name='gongj'}
person = Person{id=4, name='gongj', address='Shanghai'}
Copy the code

Subinterface: AnnotatedBeanDefinition

// About its bean class - no need to load the class.
public interface AnnotatedBeanDefinition extends BeanDefinition {
    // Get the metadata for the bean definition annotation
	AnnotationMetadata getMetadata(a);

// Gets metadata for the factory method defined by this bean, or null if not
	@Nullable
	MethodMetadata getFactoryMethodMetadata(a);
}
Copy the code

This interface can return two classes of metadata:

  • AnnotationMetadata: Performs operations on Bean annotation information, such as retrieving all annotations of the current Bean annotation and determining whether a specified annotation is included.
public interface AnnotationMetadata extends ClassMetadata.AnnotatedTypeMetadata {

	// Get all annotations fully qualified class names
	default Set<String> getAnnotationTypes(a) {
		return getAnnotations().stream()
				.filter(MergedAnnotation::isDirectlyPresent)
				.map(annotation -> annotation.getType().getName())
				.collect(Collectors.toCollection(LinkedHashSet::new));
	}

	// Get the class fully qualified name of the meta annotation corresponding to annottationName
	default Set<String> getMetaAnnotationTypes(String annotationName) { MergedAnnotation<? > annotation = getAnnotations().get(annotationName, MergedAnnotation::isDirectlyPresent);if(! annotation.isPresent()) {return Collections.emptySet();
		}
		return MergedAnnotations.from(annotation.getType(), SearchStrategy.INHERITED_ANNOTATIONS).stream()
				.map(mergedAnnotation -> mergedAnnotation.getType().getName())
				.collect(Collectors.toCollection(LinkedHashSet::new));
	}

	// Whether to include specified annotations
	default boolean hasAnnotation(String annotationName) {
		return getAnnotations().isDirectlyPresent(annotationName);
	}

	// Determine if there is a meta annotation
	default boolean hasMetaAnnotation(String metaAnnotationName) {
		return getAnnotations().get(metaAnnotationName,
				MergedAnnotation::isMetaPresent).isPresent();
	}

	Return true whenever one of the methods in the class has the specified annotation
	default boolean hasAnnotatedMethods(String annotationName) {
		return! getAnnotatedMethods(annotationName).isEmpty(); }// Returns all method meta information marked with the specified annotation
	Set<MethodMetadata> getAnnotatedMethods(String annotationName);

	// Factory method to create a new AnnotationMetadata instance for a given class using standard reflection
	static AnnotationMetadata introspect(Class
        type) {
		returnStandardAnnotationMetadata.from(type); }}Copy the code
  • MethodMetadata: The metadata class for a method. Get the method name, the full class name of the class to which the method belongs, whether it is abstract, whether it is static, whether it is final, and so on.
public interface MethodMetadata extends AnnotatedTypeMetadata {

	// Return the method name
	String getMethodName(a);

	// Returns the fully qualified name of the class to which the method belongs
	String getDeclaringClassName(a);

	// Returns the fully qualified name of the method return type
	String getReturnTypeName(a);

	// Whether a method is a valid abstract method: that is, marked abstract or declared regular on the class,
	// Non-default methods in the interface.
	boolean isAbstract(a);

	// Whether the method is declared 'static'.
	boolean isStatic(a);

	// Whether the method is marked 'final'.
	boolean isFinal(a);

	// Whether the method is overwritable: that is, it is not marked static, final, or private.
	boolean isOverridable(a);

}

Copy the code

The interface has three children: ScannedGenericBeanDefinition, ConfigurationClassBeanDefinition, AnnotatedGenericBeanDefinition

ScannedGenericBeanDefinition

It implements AnnotatedBeanDefinition and inherits GenericBeanDefinition. This BeanDefinition is used to describe annotation @ Component, @ Service, @ Controller comment marker for ScannedGenericBeanDefinition class parses.

Its source code is very simple, is more than a property: metadata used to store scanned Bean annotations information.

public class ScannedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition {

	private final AnnotationMetadata metadata;

    / * * * given MetadataReader description, for the class to create a new ScannedGenericBeanDefinition * /
	public ScannedGenericBeanDefinition(MetadataReader metadataReader) {
		Assert.notNull(metadataReader, "MetadataReader must not be null");
		this.metadata = metadataReader.getAnnotationMetadata();
		setBeanClassName(this.metadata.getClassName());
	}


	@Override
	public final AnnotationMetadata getMetadata(a) {
		return this.metadata;
	}

	@Override
	@Nullable
	public MethodMetadata getFactoryMethodMetadata(a) {
		return null; }}Copy the code

validation

@ Component, @ Service, @ Controller comment marker for ScannedGenericBeanDefinition class will parse

New AppConfig class

@ComponentScan("com.gongj")
public class AppConfig {}Copy the code

Then create the HelloController class

@Controller
public class HelloController {}Copy the code

Start the

public static void main(String[] args) {
	AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
	BeanDefinition helloController = context.getBeanFactory().getBeanDefinition("helloController");
}
Copy the code

AnnotatedGenericBeanDefinition

This class inherits from GenericBeanDefinition and implements the AnnotatedBeanDefinition interface. This BeanDefinition is used to describe annotation using the @ Configuration annotation tag Configuration class will be resolved as AnnotatedGenericBeanDefinition.

public class AnnotatedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition {

	// Annotate metadata
	private final AnnotationMetadata metadata;

	@Nullable
	private MethodMetadata factoryMethodMetadata;


	/ * * * for a given bean class to create a new AnnotatedGenericBeanDefinition *@paramBeanClass the loaded bean class */
	public AnnotatedGenericBeanDefinition(Class
        beanClass) {
		setBeanClass(beanClass);
		// What annotations are currently on the class
		this.metadata = AnnotationMetadata.introspect(beanClass);
	}

	/ * * * * for a given to create a new annotation metadata AnnotatedGenericBeanDefinition, incoming AnnotationMetadata * /
	public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata) {
		Assert.notNull(metadata, "AnnotationMetadata must not be null");
		if (metadata instanceof StandardAnnotationMetadata) {
			setBeanClass(((StandardAnnotationMetadata) metadata).getIntrospectedClass());
		}
		else {
			setBeanClassName(metadata.getClassName());
		}
		this.metadata = metadata;
	}

	/** ** based on an annotated class and factory methods on that class. , for a given to create a new annotation metadata AnnotatedGenericBeanDefinition, * /
	public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata, MethodMetadata factoryMethodMetadata) {
		this(metadata);
		Assert.notNull(factoryMethodMetadata, "MethodMetadata must not be null");
		setFactoryMethodName(factoryMethodMetadata.getMethodName());
		this.factoryMethodMetadata = factoryMethodMetadata;
	}


	@Override
	public final AnnotationMetadata getMetadata(a) {
		return this.metadata;
	}

	@Override
	@Nullable
	public final MethodMetadata getFactoryMethodMetadata(a) {
		return this.factoryMethodMetadata; }}Copy the code

validation

New MyConfig class

@Configuration
public class MyConfig {}Copy the code

Start the

public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
		BeanDefinition myConfig = context.getBeanFactory().getBeanDefinition("myConfig");
	}
Copy the code

If using AppConfig as scan package, the actual type is ScannedGenericBeanDefinition MyConfig, of course, this related to start at the back of the post.

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		BeanDefinition myConfig = context.getBeanFactory().getBeanDefinition("myConfig");
Copy the code

ConfigurationClassBeanDefinition

It is ConfigurationClassBeanDefinitionReader a private static inner class: This class is responsible for @ Bean annotation method is converted to the corresponding ConfigurationClassBeanDefinition class, source but much explanation, and before a few BeanDefinition almost.

Its functional features are as follows:

  • 1. If the @bean annotation does not specify the Bean name, the method name is used as the Bean name by default.

  • A class annotated with @Configuration, @Component, @Service will become a factory class, and a method annotated with @Bean will become a factory method that instantiates the Bean.

    validation

    Add a method to MyConfig class:

@Bean("mz")
	public User myUserBean(a){
		return new User();
	}
Copy the code

Start the

public static void main(String[] args) {
	AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
	BeanDefinition mz = context.getBeanFactory().getBeanDefinition("mz");
	User myUserBean = (User)context.getBean("mz");
	System.out.println("mz =" + mz);
	System.out.println("myUserBean = " + myUserBean);
}
Copy the code

Spring initialization time, can use GenericBeanDefinition or ConfigurationClassBeanDefinition (using the @ Bean annotations annotation class) to store user custom Bean, the initialization beans, It converts it to RootBeanDefinition.

Songko: Spring source code fourth bomb! Understand the BeanDefinition in depth

——BeanDefinition (RootBeanDefinition, ChildBeanDefinition)

Spring (4) core container – BeanDefinition resolution

Big guy: Use of Spring Metadata