Review the IOC container

The IOC container is a container that provides users with the ability to create, manage, and obtain their class instances. When users need to use class objects, they only need to ask the IOC container. In this way, they can achieve the decoupling from specific classes and provide the foundation for other advanced functions and features.

Before an IOC container can be used, the following needs to be done:

There are three ways to use Spring

<? xml version="1.0" encoding="UTF-8"? > <beans> <bean id="girl" class="di.MagicGirl"
     init-method="start" destroy-method="end">
        <constructor-arg type="java.lang.String" value="girl"></constructor-arg>
        <property name="friend" ref="boy"></property>
    </bean>

    <bean id="boy" class="di.Lad">
        <constructor-arg type="java.lang.String" value="boy"></constructor-arg>
        <constructor-arg type="di.MagicGirl" value="girl"></constructor-arg>
    </bean>
</beans>
Copy the code

XML to specify the scope of the scan package:

<context:component-scan base-package="demo.beans" />
Copy the code

Using ApplicationContext:

 ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
Copy the code
  1. Annotate how the configuration is done
@Component(initMethodName = "init", destroyMethodName = "destroy")
public class Lad implements Boy {

    @Autowired
    private Girl friend;
    
    public Lad(String name) {
        this.name = name;
    }
    
    @Autowired
    public Lad(@Value("tony") String name, @Qualifier("flower") Girl gf) {
        this.name = name;
        this.friend = gf;
        System.out.println("Constructor with Girl argument called"); }}Copy the code

Specify the scope of the package to be scanned by means of annotations:

@Configuration
@ComponentScan(basePackages = "demo.beans")
public class AppConfig {}Copy the code

Or use the following code:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Application.class);
context.scan("demo.beans");
context.refresh();
Copy the code
  1. JavaBean configuration
@Configuration
@ComponentScan(basePackages = "demo.beans")
public class AppConfig {

    @Bean
    public Lad lad(a) {
        return new Lad(""); }}Copy the code

As you can see from the above brief introduction, when you want to use Spring, you only need to use the API provided by Spring for the ApplicationContext, which is the IOC container


The inheritance of ApplicationContext

Before you look at the source code, you need to know what ApplicationContext is, what it can do, how to use it, and what its implementation classes are, what are the differences, and what is the initialization process?

ApplicationContext is the IOC container and is a common interface that provides the application configuration of the IOC container.

Take a look at the ApplicationContext interface:

public interface ApplicationContext extends EnvironmentCapable.ListableBeanFactory.HierarchicalBeanFactory.MessageSource.ApplicationEventPublisher.ResourcePatternResolver {}Copy the code

Here are the methods provided by the ApplicationContext interface:

The specific functions of each method are as follows:

The method name role
getId() Unique ID of the IOC container
getApplicationName() Returns the name of the application
getDisplayName() Show the name, explain the use, so that others easier to understand
getStartupDate() The time when the container was started
getParent() Get the parent container, similar to the parent and child factory
getAutowireCapableBeanFactory() Get the auto-assembly Bean factory

The parent interface of ApplicationContext

As you can see from the above source code, ApplicationContext has many parent interfaces:

Here’s what each parent interface does:

The parent interface role
EnvironmentCapable Propertiess file with the function of getting environment-related parameters
ListableBeanFactory A BeanFactory that provides Bean iteration capabilities
HierarchicalBeanFactory A BeanFactory that provides access to the parent container
MessageSource Basic interface to support internationalization files
ApplicationEventPublisher Apply the event publishing interface
ResourcePatternResolver Interface for resource parsing and loading

Here is the UML class diagram:

The Environment interface is used to represent the running Environment of the entire application. To better understand the Environment interface, you can imagine the running Environment of Spring as two parts. One part is the Spring application itself, and the other part is the Environment of the Spring application.

HierarchicalBeanFactory interface, the parent can be obtained, only children can obtain the parent, and containsLocalBean method is used to determine if the factory contains a Bean:

public interface HierarchicalBeanFactory extends BeanFactory {

	/**
	 * Return the parent bean factory, or {@code null} if there is none.
	 */
	@Nullable
	BeanFactory getParentBeanFactory(a);

	/**
	 * 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.
	 * @param name the name of the bean to query
	 * @return whether a bean with the given name is defined in the local factory
	 * @see BeanFactory#containsBean
	 */
	boolean containsLocalBean(String name);

}
Copy the code

The implementation of ApplicationContext

From the picture above you can see, after AbstractApplicationContext is divided into two parts, one part is the implementation of XML, the other part is the general implementation.

  1. ConfigurableApplicationContext interface
public interface ConfigurableApplicationContext extends ApplicationContext.Lifecycle.Closeable {... }Copy the code

From the picture above you can see, ConfigurableApplicationContext interface provides a lot of set methods, and only the get method in ApplicationContext interface, so you can know, ConfigurableApplicationContext interface can be configured ApplicationContext, provides the parent container, the environment, the BeanFactory post processor, listener configuration method, etc.

But also provide a method to obtain ConfigurableListableBeanFactory, and implement the Lifecycle, Closeable interface, which means it can be the life cycle of control and closing operation.

  1. AbstractApplicationContext abstract implementation class
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {... }Copy the code

AbstractApplicationContext inherited DefaultResourceLoader, defaults to the classpath resource loader

Looking at the source code, you can see that this class implements many common methods, Including ApplicationContext, ConfigurableApplicationContext, the BeanFactory, ListableBeanFactory, HierarchicalBeanFactory, MessageSourc E, ResourcePatternResolver, Lifecycle 8 parent interface method implementation, the main purpose is to reduce a lot of burden for the implementation of the subclass, The main remaining methods are refreshBeanFactory, closeBeanFactory, and getBeanFactory, which are implemented by concrete subclasses

	//---------------------------------------------------------------------
	// Abstract methods that must be implemented by subclasses
	//---------------------------------------------------------------------

	protected abstract void refreshBeanFactory(a) throws BeansException, IllegalStateException;

	protected abstract void closeBeanFactory(a);

	@Override
	public abstract ConfigurableListableBeanFactory getBeanFactory(a) throws IllegalStateException;
Copy the code

From AbstractApplicationContext came after two branches: AbstractRefreshableApplicationContext, GenericApplicationContext

  1. AbstractRefreshableApplicationContext class
 * @author Juergen Hoeller
 * @author Chris Beams
 * @since 1.13.
 * @see #loadBeanDefinitions
 * @see org.springframework.beans.factory.support.DefaultListableBeanFactory
 * @see org.springframework.web.context.support.AbstractRefreshableWebApplicationContext
 * @see AbstractXmlApplicationContext
 * @see ClassPathXmlApplicationContext
 * @see FileSystemXmlApplicationContext
 * @see org.springframework.context.annotation.AnnotationConfigApplicationContext
 */
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {}Copy the code

Abstract implementation, available since version 1.1.3, provides an implementation of the Bean factory refresh method that can be configured to override the Bean definition and loop dependencies

  1. AbstractRefreshableConfigApplicationContext class
public abstract class AbstractRefreshableConfigApplicationContext extends AbstractRefreshableApplicationContext
		implements BeanNameAware.InitializingBean {}Copy the code

AbstractRefreshableConfigApplicationContext increased resource allocation, entrance by Environment analyze the allocation of real resources path string.

  1. AbstractXmlApplicationContext
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {}Copy the code

AbstractXmlApplicationContext inside mainly implements some Bean definitions of load

ClassPathXmlApplicationContext, FileSystemXmlApplicationContext is the concrete implementation of XML resource loading way

  1. GenericApplicationContext
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
    private final DefaultListableBeanFactory beanFactory;
}
Copy the code

It implements the BeanDefinitionRegistry interface, which defines the registration behavior of bean definition information. That we can directly into GenericApplicationContext registered bean definition

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
                throws BeanDefinitionStoreException {

        this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
Copy the code

Related implementations are:

AnnotationConfigApplicationContext annotation configuration

GenericGroovyApplicationContext groovy configuration

GenericXmlApplicationContext general-purpose XML configuration

StaticApplicationContext Static resource configuration mode

As can be seen from the source AbstractRefreshableApplicationContext is inherited gradually expand, GenericApplicationContext is modular extensions

Examples of the use of the above classes:

@Configuration
@ComponentScan("edu.dongnao.courseware")
public class Application {
    
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        Lad cs = context.getBean("swk", Lad.class);
        cs.sayLove();
        
        ApplicationContext context1 = new FileSystemXmlApplicationContext("F:/workspace/idea/vip/spring-source/src/main/resources/application.xml");
        cs = context1.getBean("lad", Lad.class);
        cs.sayLove();

        context1 = new GenericXmlApplicationContext("file:F:/workspace/idea/vip/spring-source/src/main/resources/application.xml");
        cs = context1.getBean("swk", Lad.class);
        cs.sayLove();

        // The annotation method
        ApplicationContext context2 = new AnnotationConfigApplicationContext(Application.class);
        Lad cs2 = context2.getBean(Lad.class);
        cs2.sayLove();

        System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -");
        GenericApplicationContext context3 = new GenericApplicationContext();
        new XmlBeanDefinitionReader(context3).loadBeanDefinitions("classpath:application.xml");
        new ClassPathBeanDefinitionScanner(context3).scan("edu.dongnao.courseware");
        // Be sure to refresh
        context3.refresh();
        cs2 = context3.getBean("swk", Lad.class);
        cs2.sayLove();
        MagicGril ab = context3.getBean(MagicGril.class);
        ab.start();
        
        Like GenericApplicationContext / / usage
        // ApplicationContext context4 = new StaticApplicationContext();}}Copy the code

The initialization of the ApplicationContext

Take the case of ClassPathXmlApplicationContext:

Trace the code path:

The refresh method is the main part, and each of these methods is an important step:

@Override
public void refresh(a) throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
                // Prepare this context for refreshing.
                // In preparation for the refresh, initialize various states, startup time, deactivated state, configuration file information, etc
                prepareRefresh();

                // Tell the subclass to refresh the internal bean factory.
                // Notify subclasses to refresh the internal BeanFactory and return the refreshed BeanFactory
                // Notice the difference between the two subclasses of the refreshBeanFactory method
                / / AbstractRefreshableApplicationContext# refreshBeanFactory rebuilding, Complete build BeanDefinition analytical / / GenericApplicationContext# refreshBeanFactory is to set the ID, and can refresh only once
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

                // Prepare the bean factory for use in this context.
                // Prepare the BeanFactory for the container and configure the related properties
                prepareBeanFactory(beanFactory);

                try {
                        // Allows post-processing of the bean factory in context subclasses.
                        // Allow subclasses to handle the post-beanFactory
                        postProcessBeanFactory(beanFactory);

                        // Invoke factory processors registered as beans in the context.
                        // Call the method that registers the BeanFactory post-processor interface instance Bean
                        invokeBeanFactoryPostProcessors(beanFactory);

                        // Register bean processors that intercept bean creation.
                        // Register the bean instance bean of the post-processor interface
                        registerBeanPostProcessors(beanFactory);

                        // Initialize message source for this context.
                        // Initialize the internationalization resource
                        initMessageSource();

                        // Initialize event multicaster for this context.
                        // Initializes the event spreader
                        initApplicationEventMulticaster();

                        // Initialize other special beans in specific context subclasses.
                        //Refresh event to initialize some specified beans
                        onRefresh();

                        // Check for listener beans and register them.
                        // Register the listener bean
                        registerListeners();

                        // Instantiate all remaining (non-lazy-init) singletons.
                        // Complete the initialization of the bean factory, initializing all non-lazy-loaded singleton beans
                        finishBeanFactoryInitialization(beanFactory);

                        // Last step: publish corresponding event.
                        // Finally, publish the finishRefresh event
                        finishRefresh();
                }

                catch (BeansException ex) {
                        if (logger.isWarnEnabled()) {
                                logger.warn("Exception encountered during context initialization - " +
                                                "cancelling refresh attempt: " + ex);
                        }

                        // Destroy already created singletons to avoid dangling resources.
                        // All singleton beans that have been created are destroyed
                        destroyBeans();

                        // Reset 'active' flag.
                        // Reset the active flag
                        cancelRefresh(ex);

                        // Propagate exception to caller.
                        throw ex;
                }

                finally {
                        // Reset common introspection caches in Spring's core, since we
                        // might not ever need metadata for singleton beans anymore...resetCommonCaches(); }}}Copy the code

This article is about the source code of ApplicationContext and the initialization process. The source code will be analyzed later.