Spring annotation configuration startup process, spring annotation process

Source: Internet
Author: User

Spring annotation configuration startup process, spring annotation process

Recently I saw the spring source code and suddenly wanted to know how spring started itself through a class inherited from AbstractAnnotationConfigDispatcherServletInitializer without the web. xml configuration. In view of the limited capabilities and the first time I read the source code and blog, please forgive me if I cannot find it ~

 

The ide I use is IntelliJ IDEA, which is a little more convenient than myEclipse to view the source code, and the black background is quite fond. The project then runs the tomcat7 plug-in under maven. The spring version is 4.3.2.RELEASE.

 

If you have written spring web with pure annotation configuration, you should know that you need to inherit an initialization class to load beans. Then, from this class, we will load our custom functions and beans, below is one of my WebInitializer

 1 @Order(1) 2 public class WebMvcInit extends AbstractAnnotationConfigDispatcherServletInitializer { 3     protected Class<?>[] getRootConfigClasses() { 4         return new Class[]{RootConfig.class,WebSecurityConfig.class}; 5     } 6  7     protected Class<?>[] getServletConfigClasses() { 8         return new Class[]{WebConfig.class}; 9     }10 11     protected String[] getServletMappings() {12         return new String[]{"/"};13     }14 15     @Override16     protected Filter[] getServletFilters() {17         return new Filter[]{new HiddenHttpMethodFilter()};18     }19 20 }

 

First, let's take a look at the AbstractAnnotationConfigDispatcherServletInitializer class structure. This is also a uml function of IDEA. Right-click Diagrams in the class and choose show Diagrams.

Click AbstractAnnotationConfigDispatcherServletInitializer. We can see that this class is very simple and there are only four methods. Then let's take a look at createRootApplicationContext ()

 1 @Override 2     protected WebApplicationContext createRootApplicationContext() { 3         Class<?>[] configClasses = getRootConfigClasses(); 4         if (!ObjectUtils.isEmpty(configClasses)) { 5             AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext(); 6             rootAppContext.register(configClasses); 7             return rootAppContext; 8         } 9         else {10             return null;11         }12     }

 

This method probably means to get the RootClasses passed by the user (programmer), and then register the beans in it. These are not our concerns, but this method should be executed after startup, so we can find it from this method.

In IDEA, Ctrl + G can call a method or class and set the search range to project and library.

We found that the invoke (ServletContext servletContext) method under AbstractContextLoaderInitializer calls createRootApplicationContext () of the subclass to obtain WebApplicationContext and continues to find the caller of the registerContextLoaderListener (ServletContext servcontext) method, the onStartup (ServletContext servletContext) under the class is found, and the AbstractContextLoaderInitializer class is attached below.

 1 public abstract class AbstractContextLoaderInitializer implements WebApplicationInitializer { 2  3     /** Logger available to subclasses */ 4     protected final Log logger = LogFactory.getLog(getClass()); 5  6  7     @Override 8     public void onStartup(ServletContext servletContext) throws ServletException { 9         registerContextLoaderListener(servletContext);10     }11 12     /**13      * Register a {@link ContextLoaderListener} against the given servlet context. The14      * {@code ContextLoaderListener} is initialized with the application context returned15      * from the {@link #createRootApplicationContext()} template method.16      * @param servletContext the servlet context to register the listener against17      */18     protected void registerContextLoaderListener(ServletContext servletContext) {19         WebApplicationContext rootAppContext = createRootApplicationContext();20         if (rootAppContext != null) {21             ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);22             listener.setContextInitializers(getRootApplicationContextInitializers());23             servletContext.addListener(listener);24         }25         else {26             logger.debug("No ContextLoaderListener registered, as " +27                     "createRootApplicationContext() did not return an application context");28         }29     }30 31     /**32      * Create the "<strong>root</strong>" application context to be provided to the33      * {@code ContextLoaderListener}.34      * <p>The returned context is delegated to35      * {@link ContextLoaderListener#ContextLoaderListener(WebApplicationContext)} and will36      * be established as the parent context for any {@code DispatcherServlet} application37      * contexts. As such, it typically contains middle-tier services, data sources, etc.38      * @return the root application context, or {@code null} if a root context is not39      * desired40      * @see org.springframework.web.servlet.support.AbstractDispatcherServletInitializer41      */42     protected abstract WebApplicationContext createRootApplicationContext();43 44     /**45      * Specify application context initializers to be applied to the root application46      * context that the {@code ContextLoaderListener} is being created with.47      * @since 4.248      * @see #createRootApplicationContext()49      * @see ContextLoaderListener#setContextInitializers50      */51     protected ApplicationContextInitializer<?>[] getRootApplicationContextInitializers() {52         return null;53     }54 55 }

 

Note that the AbstractDispatcherServletInitializer abstract class (see the uml diagram) is skipped here. This class mainly configures DispatcherServlet, and here is the implementation of spring mvc and other functions.

 

Who will load AbstractContextLoaderInitializer? WebApplicationInitializer is already an interface and will not be called in an abstract class. So I tried to search for the WebApplicationInitializer interface, because a large project such as spring must be interface-oriented, therefore, the call is generally a write interface, and then we find the SpringServletContainerInitializer class, which implements the ServletContainerInitializer interface. This class is about to start all WebApplicationInitializer once, it can be said that this class is very close to our goal. Next, paste SpringServletContainerInitializer.

 1 @HandlesTypes(WebApplicationInitializer.class) 2 public class SpringServletContainerInitializer implements ServletContainerInitializer { 3     @Override 4     public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) 5             throws ServletException { 6  7         List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>(); 8  9         if (webAppInitializerClasses != null) {10             for (Class<?> waiClass : webAppInitializerClasses) {11                 // Be defensive: Some servlet containers provide us with invalid classes,12                 // no matter what @HandlesTypes says...13                 if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&14                         WebApplicationInitializer.class.isAssignableFrom(waiClass)) {15                     try {16                         initializers.add((WebApplicationInitializer) waiClass.newInstance());17                     }18                     catch (Throwable ex) {19                         throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);20                     }21                 }22             }23         }24 25         if (initializers.isEmpty()) {26             servletContext.log("No Spring WebApplicationInitializer types detected on classpath");27             return;28         }29 30         servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");31         AnnotationAwareOrderComparator.sort(initializers);32         for (WebApplicationInitializer initializer : initializers) {33             initializer.onStartup(servletContext);34         }35     }36 37 }

In the final foreach, start all WebApplicationInitializer. So the question is, who will start SpringServletContainerInitializer? spring cannot start it on its own.

In the web environment, only web containers are available. We can set a breakpoint somewhere above and Debug it (in fact, we can Debug = in the whole process, so it is accurate and fast, but this does not mean anything we look, nice scenery along the road)

 

We can see the startInternal method of the StandardContext class under org. apache. catalina. core. This is already the scope of tomcat, so our goal is achieved. Note that the ServletContainerInitializer interface is not under the spring package, but javax. servlet

I guess tomcat uses javax. servlet's ServletContainerInitializer interface comes to the class that implements this interface under the container, and then calls their OnStartUp. Then spring's SpringServletContainerInitializer can start all WebApplicationInitializer, among them, we have our own WebInitializer. In addition, spring security uses annotation configuration to implement WebApplicationInitializer startup. Therefore, spring is highly scalable. Take a look at the tomcat source code over the past few days to learn about the tomcat mechanism.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.