I just generated a WAR packaging app with spring boot initializer and here are the generated sources.
Main application class
@SpringBootApplication
public class ChargingListenerApplication {
public static void main(String[] args) {
SpringApplication.run(ChargingListenerApplication.class, args);
}
}
the servlet initializer class.
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(ChargingListenerApplication.class);
}
}
How does Spring realize this class and run configure()? Is this just because of the type? If so isn't this a bit weird to handle like this, instead of a proper annotation? Plus, in Spring documentation they extend SpringBootServletInitializer
in the main class.
CodePudding user response:
Yes, it is because you are extending SpringBootServletInitializer
. It makes use of Spring Framework’s servlet 3.0 support and lets you configure your application when it is launched by the servlet container, which means your custom ServletInitializer.configure()
will actually be called.
And yes, in Spring documentation they extend SpringBootServletInitializer
in the main class, but that does not mean that you can't also place it someplace else. The only weird thing is that they do recommend one thing (extending it in the main class) but the initializer does another (creating a separate class), but maybe it is on purpose for clarity reasons.
CodePudding user response:
So first of all, Spring-web module has a class SpringServletContainerInitializer
which has the definition as below.
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {...}
For the Annotation HandlesTypes,
The classes in which a
ServletContainerInitializer
has expressed interest. If an implementation of ServletContainerInitializer specifies this annotation, the Servlet container must pass the Set of application classes that extend, implement, or have been annotated with the class types listed by this annotation to theServletContainerInitializer.onStartup(java.util.Set>,
javax.servlet.ServletContext)
method of the ServletContainerInitializer (if no matching classes are found, null must be passed instead)
@Target(value=TYPE)
@Retention(value=RUNTIME)
public @interface HandlesTypes {..}
ServletContainerInitializer
is servlet interface that a container runs all of it's implementations during the startup (ofc implementations must be registered via META-INF/services/javax.servlet.ServletContainerInitializer )
So, spring checks in registered SpringServletContainerInitializer
class for types passed to the it via container and runs their onStartup methods respectively.