9. BeanFactory Source Code Analysis of Spring

BeanFactory Source Code Analysis for Spring (1)

Note: This essays is entirely quoted from https://blog.csdn.net/u014634338/article/details/82865644 , well written, thank you very much. Copying is an accumulation, I'm afraid I can't find it later.

BeanFactory

BeanFactory provides the functionality of the most basic IOC container. BeanFactory is only an interface class and does not give a specific implementation of the container. Of course, it has different implementation classes to define or extend a function.The main character of this article is it.

Start IOC Container

Here is a simple code to programmatically start the IOC container:

public void TestDefaultListableBeanFactory(){

  ClassPathResource resource  = new ClassPathResource("spring.xml");

  DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

  XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);

  reader.loadBeanDefinitions(resource);

  MyBean bean = factory.getBean(MyBean.class);

  System.out.println(bean.toString());
}

The spring.xml configuration file is simple:

<bean id="myBean" class="com.study.spring.bean.MyBean" />

In this way, we can use the DefaultListableBeanFactory IOC container through the factory object, which requires the following steps:
1) Create Abstract resources for IOC profiles, which are profiles

2) Create a BeanFactory using DefaultListableBeanFactory

3) Create a reader that loads BeanDefinition, where you use XmlBeanDefinition Reader to load BeanDefinition as an XML file.

4) Read configuration information from a defined resource location, and the specific parsing process is done by the XmlBeanDefinitionReader.

spring can be started with a short code, and the core is the DefaultListableBeanFactory, so don't directly track the process for now, or just look at the entire BeanFactory design.

BeanFactory Class Structure System

BeanFactory, also known by name, is the factory (container) for the production management beans responsible for the production and management of individual bean instances.

Let's look at the main inheritance structures associated with the BeanFactory interface:

The inheritance relationship above removes classes that are not currently needed.

emmmmm, this picture looks a bit big, slowly, first focus on the left part, comb the functions of each BeanFactory, how to comb?, see the source code.

BeanFactory

BeanFactory is a top-level interface that defines the most basic form of an IOC container.

public interface BeanFactory {

    //You can leave it unattended for the moment
    String FACTORY_BEAN_PREFIX = "&";

    Object getBean(String name) throws BeansException;
    ... //Omit other methods
}

There are some basic interfaces defined, such as Get Beans and, of course, other interfaces, which are not listed here and need to be understood by yourself.

As for FACTORY_BEAN_PREFIX, which can be ignored here, let's just mention here. If you don't understand it, there is a class called FactoryBean, which is very similar to BeanFactory. It's easy to confuse the name. BeanFactory is Factoyr first, and FactoryBean is a bean, it's just a special bean. This special bean produces another kind of bean, for ordinary peopleA bean of FactoryBean can be obtained by BeanFactory's getBean method. For FactoryBean, a bean produced by FactoryBean, not FactoryBean itself, is obtained by getBean. If you want to get FactoryBean itself, you can prefix it with &, then spring knows you need FactoryBean.This might be in the AOP section later, so much to begin with here.

ListableBeanFactory

public interface ListableBeanFactory extends BeanFactory {

    // Whether a given name contains a BeanDefinition
    boolean containsBeanDefinition(String beanName);

    // Total number of BeanDefinition s returned to factory
    int getBeanDefinitionCount();
    
    // Return the names of all beans in the factory
    String[] getBeanDefinitionNames();

    // Returns the name of the bean obtained for the specified type
    String[] getBeanNamesForType(ResolvableType type);
    
    //Get the name that contains a comment bean
    String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);

    // Finds a specified Bean based on the specified Bean name and annotation type
    <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
            throws NoSuchBeanDefinitionException;
}

HierarchicalBeanFactory

public interface HierarchicalBeanFactory extends BeanFactory {

    BeanFactory getParentBeanFactory();

    /**
     * Return whether the local bean factory contains a bean of the given name,
     * ignoring beans defined in ancestor contexts.
     * <p>This is an alternative to {@code containsBean}, ignoring a bean
     * of the given name from an ancestor bean factory.
     */
    boolean containsLocalBean(String name);

}

Layered BeanFactory, a very simple factory interface, implements a layer of Bean factories.Relative to the BeanFactory interface, it only extends one important function - the factory hierarchy, which allows you to specify a parent factory (container), while looking for beans, you can only look for this container, ignoring the parent container.

AutowireCapableBeanFactory

public interface AutowireCapableBeanFactory extends BeanFactory {

    //  This constant indicates that the factory does not have a Bean automatically assembled
    int AUTOWIRE_NO = 0;

    //Indicates automatic assembly by name
    int AUTOWIRE_BY_NAME = 1;

    //Indicates automatic assembly by type
    int AUTOWIRE_BY_TYPE = 2;

    //Indicates assembly according to construction method
    int AUTOWIRE_CONSTRUCTOR = 3;

    //Abandoned
    @Deprecated
    int AUTOWIRE_AUTODETECT = 4;

    <T> T createBean(Class<T> beanClass) throws BeansException;

    //  Given objects, auto-assemble according to comments, postprocessors, etc.
    void autowireBean(Object existingBean) throws BeansException;

    ...//Omit subsequent methods
}

AutowireCapable BeanFactory, which has not been studied in depth yet, adds annotation capabilities that allow you to assemble (manipulate) plants (containers) from annotations.

Summary

The three Factories above are direct relatives of the BeanFactory interface, three different styles of BeanFactory, hierarchical containers, enumerable (query) containers, auto-assembled containers, and the principle of single function. This interface design should be encountered frequently in normal work.

Next, take a look at other, more diverse BeanFactory.

ConfigurableBeanFactory

public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {

    String SCOPE_SINGLETON = "singleton";

    String SCOPE_PROTOTYPE = "prototype";
    
    //Set Parent Container
    void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;

    void setBeanClassLoader(ClassLoader beanClassLoader);

    ClassLoader getBeanClassLoader();

    void setBeanExpressionResolver(@Nullable BeanExpressionResolver resolver);

    BeanExpressionResolver getBeanExpressionResolver();

    /*
     * Set up conversion services
     */
    void setConversionService(ConversionService conversionService);

    ConversionService getConversionService();

    void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar);

    /*
     * Register Property Editor
     */
    void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass);

    void copyRegisteredEditorsTo(PropertyEditorRegistry registry);

    void setTypeConverter(TypeConverter typeConverter);

    TypeConverter getTypeConverter();

    //Set up a Bean Postprocessor
    void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);

    int getBeanPostProcessorCount();

    void registerScope(String scopeName, Scope scope);

    String[] getRegisteredScopeNames();

    Scope getRegisteredScope(String scopeName);

    void copyConfigurationFrom(ConfigurableBeanFactory otherFactory);
    /*
     * Register an alias for the specified Bean
     */
    void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException;

    BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    //Determines whether the specified Bean is a factory Bean
    boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException;

    void setCurrentlyInCreation(String beanName, boolean inCreation);

    boolean isCurrentlyInCreation(String beanName);

    void registerDependentBean(String beanName, String dependentBeanName);

    String[] getDependentBeans(String beanName);

    String[] getDependenciesForBean(String beanName);

    void destroyBean(String beanName, Object beanInstance);

    void destroyScopedBean(String beanName);

    void destroySingletons();
    
    ...//Omit partial methods

}

Configurable BeanFactory inherits HierarchicalBeanFactory, SingletonBeanRegistry

First look at the source code for the interface SingletonBeanRegistry:

SingletonBeanRegistry

public interface SingletonBeanRegistry {

    //Register a single class  
    void registerSingleton(String beanName, Object singletonObject);


    Object getSingleton(String beanName);


    boolean containsSingleton(String beanName);


    String[] getSingletonNames();

    int getSingletonCount();

    //Unclear
    Object getSingletonMutex();

}

As you can see, the interface SingletonBeanRegistry is very simple and implements the function of single class registration.

Configurable BeanFactory inherits both HierarchicalBeanFactory and SingletonBeanRegistry interfaces, that is, it inherits both hierarchical and instance class registration functions.

ConfigurableBeanFactory is just like its name. There are many interface methods in the configurable BeanFactory. I haven't studied each method in detail. Then I'll use it. Then I'll analyze it in detail. Understand it and know its approximate use.

ConfigurableListableBeanFactory

public interface ConfigurableListableBeanFactory
        extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {

    //Ignore dependency types for automatic assembly
    void ignoreDependencyType(Class<?> type);
    
    //Ignore auto-assembled interfaces
    void ignoreDependencyInterface(Class<?> ifc);

    //Return Registered Bean Definition
    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;


    Iterator<String> getBeanNamesIterator();

    ...//Ignore partial methods
}

The factory interface ConfigurableListableBeanFactory inherits three interfaces at the same time, ListableBeanFactory, AutowireCapableBeanFactory, and ConfigurableBeanFactory, which are arguably fully functional.

For the left part of the BeanFactory system, that's about the same. Now look at the right part

BeanDefinitionRegistry

As the name implies, this is a registered BeanDefinition

public interface BeanDefinitionRegistry extends AliasRegistry {

    //Given a bean name, register a new bean definition
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException;

    //Remove the corresponding Bean definition based on the specified Bean name
    void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    //Gets the corresponding Bean definition based on the specified bean name
    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    //Find if the specified Bean name contains a Bean definition
    boolean containsBeanDefinition(String beanName);

    //Returns all registered Bean definition names in this container
    String[] getBeanDefinitionNames();

    //Specifies whether the Bean name has been registered.
    int getBeanDefinitionCount();

   //Specifies whether the Bean name has been registered.
    boolean isBeanNameInUse(String beanName);

}

This interface is simple, it is the operation of BeanDefinition, but we do not yet know the structure of BeanDefinition, but it does not affect our analysis, because the name tells us that it refers to the definition of a bean, that is, to translate beans in xml into specific data structures.

Now, looking back, let's look at the DefaultListableBeanFactory class diagram

For the left part, there is a BeanFactory of various functions, for the right part, there is a function operation on BeanDefinition, for the middle part, there is a single Bean function service, and for the middle part, we have not analyzed the source code, but we already know its function well by name, and FactoryBeanRegistrySupport represents support for FactoryBean. (FactoryBean is earlier BeAnFactory makes a simple mention.

Now you have a general idea of each BeanFactory's function, so that later on you will know which module it belongs to, rather than having your head full of mud.

For DefaultListableBeanFactory, we did not analyze it, because all the methods in the above interface are implemented in DefaultListableBeanFactory, which involves a lot of details. From the code point of view, it is really difficult to analyze, but if you look at the function module, we also know what it might do, which can be said to be a comparison.Well-cooked containers. Now that we know the containers for beans, where do beans come from, of course, xml, but how do XML transform into a data structure? That needs to go back to our opening code:

public void TestDefaultListableBeanFactory(){

  ClassPathResource resource  = new ClassPathResource("spring.xml"); //3

  DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); //5

  XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);//7

  reader.loadBeanDefinitions(resour ce);//9

  MyBean bean = factory.getBean(MyBean.class); //11

  System.out.println(bean.toString());

}

Now we've got a general idea of lines 5 and 11, with 3,4,9 remaining, so let's leave that behind.

BeanDefinition

Bean's definition is mainly described by BeanDefinition. As the data structure used to wrap beans in Spring, let's first look at an inheritance structure of BeanDefinition (incomplete inheritance structure).

A BeanDefinition describes an instance of a bean, including attribute values, construction method parameter values, and more information about classes that inherit from it.

Brief Analysis of BeanDefinition Source Code

//Standard singleton scope identifier: "singleton".
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

//Scope identifier for a standard prototype scope: "prototype".
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

//Indicates that BeanDefinition is the role hint for the main part of the application.Usually corresponds to a user-defined bean.
int ROLE_APPLICATION = 0;

//Represents that the BeanDefinition is a role hint for the supporting portion of some large configuration, usually an external Component Definition.
//When you look at a particular ComponentDefinition, you think bean s are important.
//To be aware of this when viewing the overall configuration of the application.

int ROLE_SUPPORT = 1;

//Role tips indicate that a BeanDefinition is a role that provides a full background and has no relationship with the end user.

ROLE_SUPPORT =1 essentially means that I am a user, coming from the configuration file.

ROLE_INFRASTRUCTURE = 2 means that the Bean is Spring's own,

Above is some basic attribute information for BeanDifinition, which identifies the scope of the current Bean and whether the Bean is internal or external.Here's how this interface provides specific behavior for its subclasses:
1. ClassName get&set method of current Bean

//Specify the name of the bean class defined by this bean.
//Class names can be modified in the bean factory post-processing, usually replacing the original class name with its parsing variant.
void setBeanClassName(String beanClassName);

//Returns the current bean class name defined by this bean.
//It is important to note that this is not necessarily the actual class name used at run time in case the subclass definition overrides/inherits the class name of its parent class.
//Additionally, this may only be a class that calls a factory method, or it may even be empty in the case of a factory bean reference that calls the method.
//Therefore, do not think this is a type of bean defined at runtime, just use it for parsing at a separate bean definition level.
String getBeanClassName();

2.Bean's scope get&set method

//Override the target scope of this bean and specify a new scope name.
void setScope(String scope);
//Returns the name of the current target scope for this bean, or null if not determined
String getScope();

3. Lazy Loading Get&set Method

//Sets whether this bean should be delayed initialization.If {false}, the bean will be instantiated by the bean factory at startup.
//These factories perform immediate initialization of the singleton.
//Lazy Load <bean lazy-init="true/false">
void setLazyInit(boolean lazyInit);
//Returns whether the bean should be delayed in initialization, that is, not instantiated immediately at startup.Applicable only to single bean.
boolean isLazyInit();

4. Dependency Settings

//Set this bean to depend on the name of the initialized bean.The bean factory will guarantee that these beans are initialized first.
//<bean depends-on="">
void setDependsOn(String... dependsOn);
//Returns the name of the bean on which this bean depends.
String[] getDependsOn();

5. Is it an automatic transfer setting

//Sets whether this bean is a candidate for automatic assembly to other beans.
//It is important to note that this flag is designed to affect type-based automatic assembly only.
//It does not affect explicit references by name, which can be resolved even if the specified bean s are not marked as autowire candidates.
//Therefore, if the names match, automatic assembly of names will inject a bean.
void setAutowireCandidate(boolean autowireCandidate);

//Returns whether this bean is a candidate for automatic assembly to other beans.Is autowired used in other classes to inject the current Bean's
//Is it automatically assembled <bean autowire-candidate="true/false">
boolean isAutowireCandidate();

The methods or attributes in BeanDifinition are not fully enumerated. It is generally understood that the definition of Bean is mainly described by BeanDefinition. As the data structure used to wrap Beans in Spring, more interface implementations for BeanDifinition can be done as you see fit.

Summary

Now that you know the general structure of the BeanFactory, take a look at the following simple code and believe that your understanding will deepen:

public void TestDefaultListableBeanFactory(){

  DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

  AbstractBeanDefinition beanDefinition = new RootBeanDefinition(MyBean.class);

  factory.registerBeanDefinition("myBean",beanDefinition);

  //Dependency can be injected via a constructor, of course, we don't have one here
  //beanDefinition.setConstructorArgumentValues();

  //Dependencies can be injected through the setter method, but we don't have them here either
  //beanDefinition.setPropertyValues();

  MyBean bean = factory.getBean(MyBean.class);

  System.out.println(bean.toString());

}

Now that we know BeanDifinition and BeanDefinitionRegistry, we can actually register BeanDifinition manually, so that I can subdivide functionality and hierarchy again from the original code.

summary

Starting with DefaultListableBeanFactory, we have a general overview of the BeanFactory architecture, which has three direct relatives:

ListableBeanFactory, HierarchicalBeanFactory, AutowireCapableBeanFactory and AutowireCapableBeanFactory define the basic face of BeanFactory. Two more complex containers are derived under these three lineal relatives: ConfigurableBeanFactory, ConfigurableListThe ableBeanFactory, a configurable (operable) container through which beanFactories can modify beans in containers, is more advanced, integrates a single bean service and a BeanDefinition registration service, so for DefaultListableBeanFactory it is a registrable, configurable, and accessible BeanFactory, in terms of containersThe function is already complete.

Tags: Java Spring xml Attribute

Posted on Sat, 09 Nov 2019 00:42:00 -0500 by Benny Johnson