A few days ago my colleague asks me about how Spring Dispatcher servlet gets registered in Java-based config, as there is no XML used in the configuration. One thing I was (actually we both were) sure about that the class AbstractAnnotationConfigDispatcherServletInitializer
registers those servlet and all the configuration. But the question was How?
In order to understand that we will be going back to the servlet world. According to Servlet Java Doc, ServletContainerInitializer
is the interface which is used to register servlets, filters and other related stuff.
So any implementation of ServletContainerInitializer
will be notified of the web application’s startup phase using a callback method
public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
}
In above method, you’ll notice there is a parameter c of type Set<Class<?> >. You probably thinking about why it’s there. So here is another part of the magic, there is an annotation called @HandlesTypes
used alongside ServletContainerInitializer
. The annotation accepts an array of Class as an input argument.
public @interface HandlesTypes {
Class<?>[] value();
}
So any class (and its subclasses), which is passed as an argument to that annotation (HandlesTypes
) will be scanned by the container and finally, the collection of those class will be passed to ServletContainerInitializer#onStartup()
during the startup time.
Now you might be thinking, how the implementation of ServletContainerInitializer
gets picked by the container? So the answer to that question is:
According to the Java Docs
Implementations of this interface must be declared by a JAR file resource located inside the META-INF/services directory and named for the fully qualified class name of this interface and will be discovered using the runtime’s service provider lookup mechanism or a container-specific mechanism that is semantically equivalent to it. In either case, ServletContainerInitializer services from web-fragment JAR files excluded from an absolute ordering must be ignored, and the order in which these services are discovered must follow the application’s classloading delegation model.
Now come back to the Spring Era and check the spring-web*.jar (just extract the jar) and look for the file javax.servlet.ServletContainerInitializer. Inside that file, you’ll find a fully qualified class name as org.springframework.web.SpringServletContainerInitializer.
That’s it, you’ve solved the mystery!!
Now check the source code of that class (go to the GitHub), you’ll notice a class WebApplicationInitializer
inside @HandlesTypes
which is the parent class of most of the Spring’s initializers (AbstractAnnotationConfigDispatcherServletInitializer
, AbstractSecurityWebApplicationInitializer
).
Now you know how to create your own initializer.
Cheers!!! Happy coding.
Please share your thoughts. ☺ ☺
Top comments (0)