Core Container module is the foundation of Spring's whole architecture, and its core concept is Bean Factory, which makes Spring a container to help Spring manage beans, and provides DI (Dependency Injection) function to realize the dependency management of beans, using configuration to achieve the division of business code and framework code. Leave.
Context module, also known as Spring Context module, is a sub-module of Core Container module, which makes Spring truly an executable framework. This module extension implements BeanFactory, which provides many possibilities for Spring's extension and architecture inheritance, such as verification framework, scheduling framework, caching framework, template rendering framework and so on.
I. Design of Spring Context
The Spring Context pattern is a sub-module in the Spring Core Container module. Let's talk about the responsibilities of core Abstract classes.
(1) ApplicationContext is the basic function definition class of the whole container, which inherits BeanFactory, which indicates that the container is also a polymorphic implementation of the factory. In fact, it takes advantage of the proxy design method, which holds a BeanFactory instance internally, which performs the functions defined by the BeanFactory interface for it.
(2) AbstractApplicationContext is the core processing class of the whole container and the real implementer of Spring container. It uses template method internally and achieves high reuse.
High extensibility implements Spring startup, stop, refresh, event push, default implementation of BeanFactory method and registration of virtual machine callback.
(3) Generic Application Context is the easiest entity class to build Spring environment in Spring Context module. It covers the core functions of Spring Context and can be used out of the box without special customization scenarios. Annotation Config Application Context makes perfect use of the encapsulation and external simplicity of Generic Application Context. If you want to extend a lightweight Spring container suitable for your business, you can easily use Generic Application Context as a base class. Annotation Config Application Context is constructed by passing in an array of classes and creating an executable context instance to construct a runnable Spring runtime environment, which is very simple to use.
private final AnnotatedBeanDefinitionReader reader; private final ClassPathBeanDefinitionScanner scanner; public AnnotationConfigApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); } public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) { super(beanFactory); this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); } public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) { // Instantiate the annotated Bean definition to read the instance and scan the Bean instance according to the class path this(); // Register the current class array, parse and add the description of the Bean to BeanFactory register(annotatedClasses); // Start Spring Container refresh(); }
(4) AbstractRefreshable Application Context is the core parent class of Xml Web Application Context. If the current context holds BeanFactory, the current BeanFactory is closed, then a new BeanFactory is initialized for the next phase of the context lifecycle, and its parent container is still maintained when a new container is created. Quote.
2. Design of Spring Container BeanFactory
The core function of Spring is to manage beans, such as beans registration, injection, dependency and so on. Spring containers provide the feature of dependency injection to manage beans in Spring containers, and use IoC to isolate the configuration of beans from the actual application code. The core concept of Core Container module is BeanFactory, which is the core of all Spring applications. Because the core model of Spring is the Bean model, it is necessary to ensure the running of Spring application on the basis of managing Spring Bean.
BeanFactory interface is the basic responsibility definition interface in Bean container design. It defines the function of obtaining and judging Bean instances in terms of name, parameter, type and other dimensions.
3. Spring Parent-Child Context and Containers
As you can see from the Application Context, Spring provides a functional way to set parent-child references for the current BeanFactory and Application Context, which supports Spring's multi-container scenario like a one-way linked list node.
/** * Return the parent context, or {@code null} if there is no parent * and this is the root of the context hierarchy. * @return the parent context, or {@code null} if there is no parent */ @Nullable ApplicationContext getParent();
The ApplicationContext interface provides a way to acquire the parent context. Since the parent context can be acquired externally, there must be a setting method or initialization method of the context attribute. The most commonly used method is to use the construction method and set method to specify manually.
/** * Create a new AbstractApplicationContext with the given parent context. * @param parent the parent context */ public AbstractApplicationContext(@Nullable ApplicationContext parent) { this(); setParent(parent); }
When Spring parent-child containers exist in Spring MVC environment, the child containers can reuse the Bean instances of the parent containers to avoid repeated creation.
When using Spring MVC, the following configuration will appear in web.xml.
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>Hello</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-config.xml</param-value> </init-param> <!-- The server is loaded as soon as it is started --> <load-on-startup>1</load-on-startup> </servlet>
Since the < listener-class > Bian tag is loaded earlier than the < servlet > tag in web.xml, ContextLoaderListener creates a Spring container after booting, and then instantiates a container when Dispatcher starts.
HttpServletBean is a subclass of HttpServlet, which overrides the init method and invokes the following method for initialization.
@Override protected final void initServletBean() throws ServletException { // Omission.. try { // Creating Spring Web Containers this.webApplicationContext = initWebApplicationContext(); initFrameworkServlet(); } // Omission.. }
Create a Spring Web container:
protected WebApplicationContext initWebApplicationContext() { // Get the container in the Listener from the properties in the Servlet context WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); WebApplicationContext wac = null; if (this.webApplicationContext != null) { wac = this.webApplicationContext; if (wac instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; /* If the parent container is a web container and is not started, Run the current container and set its parent container. That is to say, two Spring Servlet s are configured in XML, and bean s can still be referenced to each other. */ if (!cwac.isActive()) { if (cwac.getParent() == null) { cwac.setParent(rootContext); } configureAndRefreshWebApplicationContext(cwac); } } } if (wac == null) { wac = findWebApplicationContext(); } if (wac == null) { // Create the web container created by the current Servlet and create the parent container in it wac = createWebApplicationContext(rootContext); } if (!this.refreshEventReceived) { synchronized (this.onRefreshMonitor) { // Instantiate the current container onRefresh(wac); } } if (this.publishContext) { String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); } return wac; }
AbstractRefreshableApplicationContext is the core base class of Spring Web container, calling the refreshBeanFactory method when Spring AbstractAplicationContext starts.
@Override protected final void refreshBeanFactory() throws BeansException { //If a factory already exists, destroy the beans in the factory and close the current Bean Factory if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { //Create Bean Factory DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); //Set whether the current factory Bean allows the Bean to define override coverage //Set whether the current BeanFactory allows Bean circular references customizeBeanFactory(beanFactory); //Load the Bean definition into the Bean factory according to the specified configuration loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } } protected DefaultListableBeanFactory createBeanFactory() { return new DefaultListableBeanFactory(getInternalParentBeanFactory()); } @Nullable protected BeanFactory getInternalParentBeanFactory() { //Place the factory in the parent container as the parent factory in the current container factory return (getParent() instanceof ConfigurableApplicationContext ? ((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent()); }
Because containers in Spring MVC are related (i.e. parent-child containers), containers can access each other and sub-containers can share beans of parent containers. However, the parent container cannot share the beans of the child container, because when the parent container has started, the child container has not been instantiated. If the parent container refers to the beans of the child container, it will not work properly.