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 is
AttributeAccessorSupport
, the use ofLinkedHashMap
Store 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