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:
bean Label properties 1) scope: * *Used to configure spring bean Scope of 2)singleton: * *express bean For single example 3)abstract: Set to true,Will this bean Used only as a template, the application context does not attempt to initialize it in advance 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 Note: only for singleton of bean work 5)autowire: * *automatic assembly 6)dependency - check: Dependency check 7)depends - on: * *Represents a bean The instantiation of depends on another bean Instantiate first 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 9) primary: Should bean Priority injection 10)init - method: * *initialization bean Method called when 11)destory - method: * *The method called before the container is destroyed 12)factory - method: When called factory - method The method pointed to before instantiating bean 13)factory -bean: Created by calling static factory methods bean II bean Child element of 1)meta: Metadata, which can be used when the information inside needs to be used key obtain 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 3)replaced - method: You can call new methods to replace existing methods at runtime, and dynamically update the logic of the original methods 4)constructor -arg: * * yes bean Automatically find the corresponding constructor and pass in the set parameters during initialization 5)property: * * Basic data type assignment 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)
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement { String SCOPE_SINGLETON = "singleton"; //Singleton mode String SCOPE_PROTOTYPE = "prototype"; //Prototype mode (normal) //The role of this bean int ROLE_APPLICATION = 0; //Indicates that the bean is user-defined int ROLE_SUPPORT = 1; //Indicates that the bean is a third-party plug-in or tool int ROLE_INFRASTRUCTURE = 2; //Indicates that the bean is spring's own //Set or to get the name of the parent bean of this bean void setParentName (@Nullable String var1); @Nullable String getParentName (); //Set or to get the class name of this bean void setBeanClassName (@Nullable String var1); @Nullable String getBeanClassName (); //Set or to get the mode of this bean (singleton mode or prototype mode) void setScope (@Nullable String var1); @Nullable String getScope (); //Set or to get the delayed initialization property of this bean (true, false) void setLazyInit (boolean var1); boolean isLazyInit (); //Set or get dependency void setDependsOn (@Nullable String... var1); @Nullable String[] getDependsOn(); //Set or to get whether the acceptance of this bean is automatically assembled (true, false) void setAutowireCandidate (boolean var1); boolean isAutowireCandidate (); //Set whether or get is primary (true, false) void setPrimary (boolean var1); boolean isPrimary (); //Set or to get the name of the factory bean void setFactoryBeanName (@Nullable String var1); @Nullable String getFactoryBeanName (); //Set or to get the generation method name in the factory bean void setFactoryMethodName (@Nullable String var1); @Nullable String getFactoryMethodName (); //Gets all parameter values of the constructor ConstructorArgumentValues getConstructorArgumentValues (); //Judge whether the constructor parameter is empty default boolean hasConstructorArgumentValues () { return ! this.getConstructorArgumentValues().isEmpty(); } //Get all properties MutablePropertyValues getPropertyValues (); default boolean hasPropertyValues () { return ! this.getPropertyValues().isEmpty(); } //Set or get initialization method name void setInitMethodName (@Nullable String var1); @Nullable String getInitMethodName (); //Set or get destroy method name void setDestroyMethodName (@Nullable String var1); @Nullable String getDestroyMethodName (); //Setting roles is the first three integers (0,1,2), user-defined, third-party and spring internal void setRole (int var1); int getRole (); //Set or to get the description of this bean void setDescription (@Nullable String var1); @Nullable String getDescription (); //Judge whether the bean is singleton, prototype or abstract boolean isSingleton (); boolean isPrototype (); boolean isAbstract (); //Get the resource description, this resource file @Nullable String getResourceDescription (); @Nullable BeanDefinition getOriginatingBeanDefinition (); }
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:
public interface BeanDefinitionRegistry extends AliasRegistry { // Key - > register a new BeanDefinition instance in the registry void registerBeanDefinition (String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException; // Remove the registered BeanDefinition instance from the registry void removeBeanDefinition (String beanName) throws NoSuchBeanDefinitionException; // Gets the specified BeanDefinition instance from the registry BeanDefinition getBeanDefinition (String beanName) throws NoSuchBeanDefinitionException; // Judge whether the BeanDefinition instance is in the registry (whether it is registered) boolean containsBeanDefinition (String beanName); // Gets the beanName (identity) of all BeanDefinition instances in the registry String[] getBeanDefinitionNames(); // Returns the number of BeanDefinition instances in the registry int getBeanDefinitionCount (); // Is beanName occupied boolean isBeanNameInUse (String beanName); }
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
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry { //The bottom layer is to delegate the operation to the DefaultListableBeanFactory private final DefaultListableBeanFactory beanFactory; ...... }
So we only look at the core source code of {DefaultListableBeanFactory:
// The registry consists of the BeanDefinition's identity (beanName) and its instance private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, bean>( 64); // Identity (beanName) collection private final List<String> beanDefinitionNames = new ArrayList<String>( 64); public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { // Omit other codes else { if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) synchronized ( this.beanDefinitionMap) { this.beanDefinitionMap.put(beanName, beanDefinition); List<String> updatedDefinitions = new ArrayList<>( this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll( this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; if ( this.manualSingletonNames.contains(beanName)) { Set<String> updatedSingletons = new LinkedHashSet<>( this.manualSingletonNames); updatedSingletons.remove(beanName); this.manualSingletonNames = updatedSingletons; } } } else { // Register BeanDefinition * * * * the most important sentence this.beanDefinitionMap.put(beanName, beanDefinition); this.beanDefinitionNames.add(beanName); this.manualSingletonNames.remove(beanName); } this.frozenBeanDefinitionNames = null; } if (existingDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } }
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
public interface BeanFactory { //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, //If you need to get the factory itself, you need to escape String FACTORY_BEAN_PREFIX = "&"; Here according to bean Your name, in IOC Obtained in container bean Instance, this IOC A container is a large abstract factory. Object getBean (String name) throws BeansException; //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. Object getBean (String name, Class requiredType) throws BeansException; //Here you can retrieve the bean to see if there is a bean with this name in the IOC container boolean containsBean (String name); //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 boolean isSingleton (String name) throws NoSuchBeanDefinitionException; //Here, get the Class type of the bean instance Class getType (String name) throws NoSuchBeanDefinitionException; //The alias of the bean is obtained here. If the alias is retrieved, its original name will also be retrieved String[] getAliases(String name); }
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.
- Different dimensions of functions are divided into different interfaces to facilitate future maintenance and reading by others. For example: AutowireCapableBeanFactory, ListableBeanFactory, hierarchalbeanfactory, etc
- The implementations of different interfaces are distributed in different classes to facilitate the expansion of multiple implementations of different interfaces in the future
- 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