Relationship between beandefinition, beandefinitionfactory and beandefinitionregestry

Posted by abakash on Wed, 05 Jan 2022 17:27:21 +0100

After the Spring container is started, the bean is first read xml The configuration file, then parses the definitions of various beans in the xml file, and converts each < bean / > element in the xml file into a BeanDefinition object, in which various information of the bean read from the configuration file is saved. After reading the configuration file, many BeanDefinition objects are obtained, Then register these beans in beanFactory through BeanDefinitionRegistry, which is the basic process when the Spring IOC container is started  

Let's take a closer look at the composition and functions of beandefinition, beandefinitionregistry and beanfactory  

1. BeanDefinition: store the definition information of the bean into the corresponding attribute of the BeanDefinition, and then the operation on the bean is directly carried out on the BeanDefinition The attributes defined in this interface include class name, scscope, attribute, constructor parameter list, dependent bean, whether singleton class, etc  
It inherits the attributeaccess and BeanMetadataElement interfaces   

  • AttributeAccessor interface: defines the modification of attributes, including obtaining, setting and deleting.
  • Beanmetadataelement, the configuration element held by the bean meta object can be obtained through the getSource() method.

BeanDefinition corresponds to the attribute information of the < bean > element configuration. The list is as follows:

    
  1. bean Label properties
  2. 1) scope: * *Used to configure spring bean Scope of
  3. 2)singleton: * *express bean For single example
  4. 3)abstract: Set to true,Will this bean Used only as a template, the application context does not attempt to initialize it in advance
  5. 4)lazy -init: * *Set as true,Delayed loading, the bean Not in ApplicationContext It is instantiated in advance at startup, but passes to the container for the first time getBean Claim bean Time instantiation
  6. Note: only for singleton of bean work
  7. 5)autowire: * *automatic assembly
  8. 6)dependency - check: Dependency check
  9. 7)depends - on: * *Represents a bean The instantiation of depends on another bean Instantiate first
  10. 8)autowire -candidate: * *Set as false,The container does not take this into account when looking for auto assemble objects bean,That is, it will not be considered as other bean Candidates for automatic assembly, but the bean Itself can be injected with other components using automatic assembly bean
  11. 9) primary: Should bean Priority injection
  12. 10)init - method: * *initialization bean Method called when
  13. 11)destory - method: * *The method called before the container is destroyed
  14. 12)factory - method: When called factory - method The method pointed to before instantiating bean
  15. 13)factory -bean: Created by calling static factory methods bean
  16. II bean Child element of
  17. 1)meta: Metadata, which can be used when the information inside needs to be used key obtain
  18. 2)lookup - method: Getter injection is to declare a method to return a certain type bean But what you actually want to return bean It is configured in the configuration file
  19. 3)replaced - method: You can call new methods to replace existing methods at runtime, and dynamically update the logic of the original methods
  20. 4)constructor -arg: * * yes bean Automatically find the corresponding constructor and pass in the set parameters during initialization
  21. 5)property: * * Basic data type assignment
  22. 6)qualifier: * * adopt Qualifier Specify injection bean Name of

The source code of BeanDefinition for packaging the above information is as follows: (the two figures can be viewed correspondingly, whether they correspond one by one)

    
  1. public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
  2. String SCOPE_SINGLETON = "singleton"; //Singleton mode
  3. String SCOPE_PROTOTYPE = "prototype"; //Prototype mode (normal)
  4. //The role of this bean
  5. int ROLE_APPLICATION = 0; //Indicates that the bean is user-defined
  6. int ROLE_SUPPORT = 1; //Indicates that the bean is a third-party plug-in or tool
  7. int ROLE_INFRASTRUCTURE = 2; //Indicates that the bean is spring's own
  8. //Set or to get the name of the parent bean of this bean
  9. void setParentName (@Nullable String var1);
  10. @Nullable
  11. String getParentName ();
  12. //Set or to get the class name of this bean
  13. void setBeanClassName (@Nullable String var1);
  14. @Nullable
  15. String getBeanClassName ();
  16. //Set or to get the mode of this bean (singleton mode or prototype mode)
  17. void setScope (@Nullable String var1);
  18. @Nullable
  19. String getScope ();
  20. //Set or to get the delayed initialization property of this bean (true, false)
  21. void setLazyInit (boolean var1);
  22. boolean isLazyInit ();
  23. //Set or get dependency
  24. void setDependsOn (@Nullable String... var1);
  25. @Nullable
  26. String[] getDependsOn();
  27. //Set or to get whether the acceptance of this bean is automatically assembled (true, false)
  28. void setAutowireCandidate (boolean var1);
  29. boolean isAutowireCandidate ();
  30. //Set whether or get is primary (true, false)
  31. void setPrimary (boolean var1);
  32. boolean isPrimary ();
  33. //Set or to get the name of the factory bean
  34. void setFactoryBeanName (@Nullable String var1);
  35. @Nullable
  36. String getFactoryBeanName ();
  37. //Set or to get the generation method name in the factory bean
  38. void setFactoryMethodName (@Nullable String var1);
  39. @Nullable
  40. String getFactoryMethodName ();
  41. //Gets all parameter values of the constructor
  42. ConstructorArgumentValues getConstructorArgumentValues ();
  43. //Judge whether the constructor parameter is empty
  44. default boolean hasConstructorArgumentValues () {
  45. return ! this.getConstructorArgumentValues().isEmpty();
  46. }
  47. //Get all properties
  48. MutablePropertyValues getPropertyValues ();
  49. default boolean hasPropertyValues () {
  50. return ! this.getPropertyValues().isEmpty();
  51. }
  52. //Set or get initialization method name
  53. void setInitMethodName (@Nullable String var1);
  54. @Nullable
  55. String getInitMethodName ();
  56. //Set or get destroy method name
  57. void setDestroyMethodName (@Nullable String var1);
  58. @Nullable
  59. String getDestroyMethodName ();
  60. //Setting roles is the first three integers (0,1,2), user-defined, third-party and spring internal
  61. void setRole (int var1);
  62. int getRole ();
  63. //Set or to get the description of this bean
  64. void setDescription (@Nullable String var1);
  65. @Nullable
  66. String getDescription ();
  67. //Judge whether the bean is singleton, prototype or abstract
  68. boolean isSingleton ();
  69. boolean isPrototype ();
  70. boolean isAbstract ();
  71. //Get the resource description, this resource file
  72. @Nullable
  73. String getResourceDescription ();
  74. @Nullable
  75. BeanDefinition getOriginatingBeanDefinition ();
  76. }

2. BeanDefinitionRegistry: define the general operation of a Bean to register BeanDefinition. Internally, it is implemented with a Map  
Main functions:

  • Register beans in the form of map < string, beandefinition >
  • Delete and get beandefinition according to beanName
  • Get the number of bean definitions held
  • Judge whether beandefinition is included according to beanName

There are three default implementation classes: simplebandefinitionregistry, DefaultListableBeanFactory and Generic ApplicationContext

BeanDefinitionRegistry source code:

    
  1. public interface BeanDefinitionRegistry extends AliasRegistry {
  2. // Key - > register a new BeanDefinition instance in the registry
  3. void registerBeanDefinition (String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;
  4. // Remove the registered BeanDefinition instance from the registry
  5. void removeBeanDefinition (String beanName) throws NoSuchBeanDefinitionException;
  6. // Gets the specified BeanDefinition instance from the registry
  7. BeanDefinition getBeanDefinition (String beanName) throws NoSuchBeanDefinitionException;
  8. // Judge whether the BeanDefinition instance is in the registry (whether it is registered)
  9. boolean containsBeanDefinition (String beanName);
  10. // Gets the beanName (identity) of all BeanDefinition instances in the registry
  11. String[] getBeanDefinitionNames();
  12. // Returns the number of BeanDefinition instances in the registry
  13. int getBeanDefinitionCount ();
  14. // Is beanName occupied
  15. boolean isBeanNameInUse (String beanName);
  16. }

The difference between its three implementation classes

Simplebeanefinitionregistry is a simple implementation of BeanDefinitionRegistry. It also inherits simpleliasregistry (a simple implementation of alias Registry). It only provides registry function without factory function. Simplebeanendefinitionregistry uses ConcurrentHashMap to store the registered BeanDefinition.

DefaultListableBeanFactory is the default implementation of ConfigurableListableBeanFactory (actually BeanFactory) and BeanDefinitionRegistry interface: a complete bean factory based on BeanDefinition metadata. It also uses the ConcurrentHashMap data structure to store the registered BeanDefinition.

GenericApplicationContext, which implements the registration and logoff functions by delegating DefaultListableBeanFactory  

    
  1. public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
  2. //The bottom layer is to delegate the operation to the DefaultListableBeanFactory
  3. private final DefaultListableBeanFactory beanFactory;
  4. ......
  5. }

So we only look at the core source code of {DefaultListableBeanFactory:

    
  1. // The registry consists of the BeanDefinition's identity (beanName) and its instance
  2. private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, bean>( 64);
  3. // Identity (beanName) collection
  4. private final List<String> beanDefinitionNames = new ArrayList<String>( 64);
  5. public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
  6. throws BeanDefinitionStoreException {
  7. // Omit other codes
  8. else {
  9. if (hasBeanCreationStarted()) {
  10. // Cannot modify startup-time collection elements anymore (for stable iteration)
  11. synchronized ( this.beanDefinitionMap) {
  12. this.beanDefinitionMap.put(beanName, beanDefinition);
  13. List<String> updatedDefinitions = new ArrayList<>( this.beanDefinitionNames.size() + 1);
  14. updatedDefinitions.addAll( this.beanDefinitionNames);
  15. updatedDefinitions.add(beanName);
  16. this.beanDefinitionNames = updatedDefinitions;
  17. if ( this.manualSingletonNames.contains(beanName)) {
  18. Set<String> updatedSingletons = new LinkedHashSet<>( this.manualSingletonNames);
  19. updatedSingletons.remove(beanName);
  20. this.manualSingletonNames = updatedSingletons;
  21. }
  22. }
  23. }
  24. else {
  25. // Register BeanDefinition * * * * the most important sentence
  26. this.beanDefinitionMap.put(beanName, beanDefinition);
  27. this.beanDefinitionNames.add(beanName);
  28. this.manualSingletonNames.remove(beanName);
  29. }
  30. this.frozenBeanDefinitionNames = null;
  31. }
  32. if (existingDefinition != null || containsSingleton(beanName)) {
  33. resetBeanDefinition(beanName);
  34. }
  35. }

3. BeanFactory: create a Bean factory. Its main method is getBean(String beanName). This method returns a Bean with a specific name from the container. The function of BeanFactory is continuously expanded through other interfaces

    
  1. public interface BeanFactory {
  2. //Here is the escape definition of FactoryBean, because if the name of the bean is used to retrieve the FactoryBean, the object obtained is the object generated by the factory,
  3. //If you need to get the factory itself, you need to escape
  4. String FACTORY_BEAN_PREFIX = "&";
  5. Here according to bean Your name, in IOC Obtained in container bean Instance, this IOC A container is a large abstract factory.
  6. Object getBean (String name) throws BeansException;
  7. //Here, the bean instance is obtained according to the bean name and Class type. The difference from the above method is that it will throw an exception: if the Class type and needs of the bean instance obtained according to the name are different.
  8. Object getBean (String name, Class requiredType) throws BeansException;
  9. //Here you can retrieve the bean to see if there is a bean with this name in the IOC container
  10. boolean containsBean (String name);
  11. //Here, the bean instance is obtained according to the bean name, and whether the bean is a single piece is judged at the same time
  12. boolean isSingleton (String name) throws NoSuchBeanDefinitionException;
  13. //Here, get the Class type of the bean instance
  14. Class getType (String name) throws NoSuchBeanDefinitionException;
  15. //The alias of the bean is obtained here. If the alias is retrieved, its original name will also be retrieved
  16. String[] getAliases(String name);
  17. }

The most common implementation of BeanFactory is DefaultListableBeanFactory, which also implements the BeanDefinitionRegistry interface, so it undertakes the registration management of beans.

The class hierarchy of DefaultListableBeanFactory is as follows:

The function of DefaultListableBeanFactory is to operate beans in the form of list collection. Why should it be split into so many classes and interfaces. This may be based on several considerations.

  1. Different dimensions of functions are divided into different interfaces to facilitate future maintenance and reading by others. For example: AutowireCapableBeanFactory, ListableBeanFactory, hierarchalbeanfactory, etc
  2. The implementations of different interfaces are distributed in different classes to facilitate the expansion of multiple implementations of different interfaces in the future
  3. From the distribution of the whole class diagram, it can be seen that spring is interface oriented programming in this area, and the implementation of the following classes. They think it is only one kind of interface function implementation, which can be expanded into a variety of implementations at any time

You can roughly understand the functions of each interface by name:

The hierarchalbeanfactory interface implements the parent-child relationship of BeanFactory on the basis of inheriting BeanFactory.
The AutowireCapableBeanFactory interface implements the automatic assembly function of beans on the basis of inheriting BeanFactory
ListableBeanFactory interface is based on inheriting BeanFactory to realize the list collection operation function of Bean
The ConfigurableBeanFactory interface implements all configuration management functions of BeanFactory on the basis of inheriting hierarchical BeanFactory
SingletonBeanRegistry is the registration interface for singleton beans
The ConfigurableListableBeanFactory interface is a comprehensive interface that inherits the three interfaces of AutowireCapableBeanFactory, ListableBeanFactory and ConfigurableBeanFactory
The alias registry interface is an alias registration interface, and the simpleliasregistry class is a simple class that implements the alias registration interface

Topics: Java Spring