[Spring analysis] i. what can BeanFactory say?

Reading the Spring source code, BeanFactory cannot avoid its existence. The common usage scenarios are also in the following forms:

ConfigurableApplicationContext ctx = SpringApplication.run(xxx.class);
BeanFactory beanFactory = (BeanFactory) ctx;
beanFactory.getBean(xxx);

But BeanFactory is not so boring.

Pre knowledge

Purchase discount www.fenfaw.com cn
  1. The core of Spring's IOC feature is: bean container, also known as bean factory - the factory for storing beans, which is responsible for adding, instantiating, initializing, monitoring and deleting beans.
  2. We know that before using Spring, we need to configure beans in XML or Annotation, so that when Spring starts, it can store corresponding bean instances into the container by loading the specified configuration file or configuration class. These definitions in the configuration file / class are called bean definitions, which are encapsulated in Spring using BeanDefinition.
  3. The configuration file / configuration class where the Bean definition is located is called the configuration source. Spring supports different configuration sources, including XML, Annotation, Groovy and even Property.
  4. There are different readers for reading different configuration sources, such as XmlBeanDefinitionReader for reading XML, PropertiesBeanDefinitionReader for reading Property, and AnnotatedBeanDefinitionReader for reading Annotation.
  5. Annotation was introduced after Java 5, so in the early stage, Spring collects Bean definitions by reading the specified configuration source; After Spring supports annotations, the configuration source is changed from configuration file to Class. Therefore, AnnotatedBeanDefinitionReader and XmlBeanDefinitionReader do not inherit from the unified parent Class, but they belong to the same module concept.

BeanFactory

In Spring, the definition of BeanFactory interface is very simple, mainly including the following methods:

<T> T getBean(Class<T> requiredType) throws BeansException;
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
// ... other

It is only responsible for obtaining and judging operations.
However, these methods alone do not meet the requirements of multi-functional BeanFactory, so BeanFactory has three subclasses with different characteristics:

ListableBeanFactory
HierarchicalBeanFactory
AutowireCapableBeanFactory
  • ListableBeanFactory: this sub interface requires the implementer to have the function of being enumerated / indexed / retrieved, so as to avoid the need to search through beanName iteratively. We will soon think of the Map structure. At the same time, the methods defined by this interface are required to pay attention to the preloaded BeanDefinition (i.e. Bean definition).
String[] getBeanDefinitionNames();
boolean containsBeanDefinition(String beanName);
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) throws NoSuchBeanDefinitionException;
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType, boolean allowEagerInit);
  • Hierarchical BeanFactory: this class is known by its name. It is a BeanFactory with hierarchical structure. It provides only the following two methods: obtaining the parent factory and judging whether the current factory contains the specified Bean.
BeanFactory getParentBeanFactory();
boolean containsLocalBean(String name);
  • AutowireCapableBeanFactory: this class is provided by Spring to support the factory of automatic assembly, injection and filling of beans, that is, the instantiation of beans is in this factory (the common instantiation process of beans is completed in this factory, and the relevant API s are defined)
<T> T createBean(Class<T> beanClass) throws BeansException;    // establish
void autowireBean(Object existingBean) throws BeansException;    // automatic assembly
Object initializeBean(Object existingBean, String beanName) throws BeansException;    // initialization
Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)  BeansException;    // Process callback
Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException;    // Process callback
void destroyBean(Object existingBean);    // Destroy

At first glance, it is found that BeanFactory is much richer and associated with BeanDefinition. After a closer look, you will find that these interfaces define acquisition or judgment methods, which are similar to BeanFactory; And they are closely related to Bean. In addition, Spring provides the configuration interface of relevant control options of BeanFactory.

Spring first provides a subclass of hierarchalbeanfactory: ConfigurableBeanFactory. It defines some related configuration entries of BeanFactory, and also defines the parent setting entry of hierarchical BeanFactory #getparentbeanfactory. Generally speaking, it is a related class of BeanFactory configuration (defining the setting and acquisition of configuration), such as the registration of Scope, the holding of type converter list, the addition of post processor, etc,

void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;    // Set parent factory
void setBeanClassLoader(@Nullable ClassLoader beanClassLoader);    // Set ClassLoader of Bean
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);     // Add BeanPostProcessor
void registerScope(String scopeName, Scope scope);    // Register Scope
Scope getRegisteredScope(String scopeName);    // Get the configured Scope information from BeanFactory
BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;    // Get the merged BeanDefinition

Factory related configurations have been. On this basis, Spring extends a new sub factory type: ConfigurableListableBeanFactory. Its inheritance relationship is as follows:

This interface inherits all the main interface types related to BeanFactory and has all the functions of the factory mentioned above. Now this type is "free and rich". Let's see what new methods it defines:

void ignoreDependencyInterface(Class<?> ifc);    // Ignore dependent interfaces, such as Aware class interface
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;    // Get the Bean definition (only get the definition in the current Bean, regardless of the level)
boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor) throws NoSuchBeanDefinitionException;    // Whether automatic injection is supported
void freezeConfiguration();    // Freeze the configuration, and the Bean definition no longer supports modification (modification means regenerating the Bean instance)
void preInstantiateSingletons() throws BeansException;    // And instantiate all singletons

Because it inherits the autowirecapablebeanfactory, it has the ability to assemble beans automatically. At the same time, on this basis, I have defined a layer of external control, such as isAutowireCandidate, freezeConfiguration, and more importantly, preInstantiateSingletons.

After all, it now has the resources: it has the ability to retrieve Bean definitions, automatic assembly control and Bean factory configuration, so it has the ability to serve as an entry for instantiating singletons.

In addition to inheriting the main Bean factory types, this interface also inherits SingletonBeanRegistry. This interface has nothing to do with other interfaces, but it is closely related to the Spring IOC feature.
As we know, beans in the Spring container have a variety of Scope ranges, and the common ones are Singleton and Prototype. However, through the above factory definition, we can see only get Bean operation, not getSingleton. In other words, Spring's top-level BeanFactory does only focus on IOC (i.e. control inversion), rather than whether the container is a Singleton or a Prototype. To obtain instance Scope information through BeanFactory, you can only use its methods: isSingleton, isPrototype. Yes, it's so pure.
Because the singleton model also plays an important role in Spring, Spring divides it into a separate concept: Singleton bean registry
Its methods include:

void registerSingleton(String beanName, Object singletonObject);    // Registration singleton (not necessarily built through Bean definition)
Object getSingleton(String beanName);    // Get singleton
boolean containsSingleton(String beanName);    // Judge whether to include single instance
String[] getSingletonNames();    // Get all singleton names
int getSingletonCount();    // Get the number of single cases

With single instance registration and acquisition.
Of course, unless it is explicitly specified that the Bean is not a singleton, it will be registered in the container after the Bean definition is parsed by default in Spring, using registerSingleton, that is, the default registered singleton type.

Based on the above results, a Bean factory with rich and perfect functions is constructed

  • Bean factory configuration
  • BeanDefinition index get
  • Trigger instantiation Bean
  • Bean instantiation, filling and initialization
  • Bean build time callback
  • Get Bean instance index
  • Bean destruction
  • Get parent factory by backtracking

Each Bean factory has a corresponding Abstract implementation. Finally, the subclass DefaultListableBeanFactory completes the unified cause and is used by ApplicationContext

The construction of Bean is based on the definition of Bean. Where does it come from?

Spring defines an abstract BeanDefinitionRegistry for BeanDefinition, which has the following methods:

void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
boolean containsBeanDefinition(String beanName);
String[] getBeanDefinitionNames();
int getBeanDefinitionCount();
boolean isBeanNameInUse(String beanName);

It has the registration, removal, acquisition and judgment of Bean definition, and is implemented by DefaultListableBeanFactory. Therefore, DefaultListableBeanFactory, as the internal factory of Spring's core class ApplicationContext, is implemented as follows:

Summary:

  1. After understanding the inheritance system of BeanFactory, you can quickly recall relevant knowledge points, such as:

    • The instantiation process of Bean must be in AutowireCapableBeanFactory, and the default implementation is the abstract class: AbstractAutowireCapableBeanFactory;
    • Bean factory has a hierarchical concept. When the current bean factory cannot obtain the corresponding information (bean instance, bean definition, etc.), it can be obtained back to the parent factory;
  2. How to better remember the relevant knowledge points of BeanFactory can be started from the aspects of function and naming, such as:

  3. Looking back at the source code, you will see the following code

Only the corresponding interface implementation can have the corresponding API for setting and obtaining.

The above is the relevant learning and summary of Bean factory. If there are mistakes and omissions, please correct them.

Added by sangamon on Thu, 10 Feb 2022 11:00:08 +0200