Fala Thiago, tudo bem ?
O ponto importante para chegarmos a como o Spring consegue chegar nos códigos de configuração da JPA (ou qualquer outra configuração), vem de um detalhe da especificação de Servlets (a partir da versão 3). Para facilitar a configuração programática (sem xml) a spec pede que os frameworks tragam dentro de seus módulos um arquivo nomeado javax.servlet.ServletContainerInitializer
.
Por mais que o nome do arquivo pareça o nome de uma classe, esse arquivo não é um .class
, mas sim um arquivo texto. No caso do Spring, esse arquivo texto tem o seguinte conteúdo.
org.springframework.web.SpringServletContainerInitializer
.. agora sim indica um nome de classe. Classe essa que será carregada pelo container Servlet que você estiver utilizando.
Dê uma olhada no conteúdo da classe...
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException {
List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>();
if (webAppInitializerClasses != null) {
for (Class<?> waiClass : webAppInitializerClasses) {
// Be defensive: Some servlet containers provide us with invalid classes,
// no matter what @HandlesTypes says...
if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
try {
initializers.add((WebApplicationInitializer) waiClass.newInstance());
}
catch (Throwable ex) {
throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
}
}
}
}
if (initializers.isEmpty()) {
servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
return;
}
AnnotationAwareOrderComparator.sort(initializers);
servletContext.log("Spring WebApplicationInitializers detected on classpath: " + initializers);
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
}
}
Perceba que o código vai procurar por qualquer initializer (classe que implemente WebApplicationInitializer direta ou indiretamente) - representado pela annotation @HandlesTypes(WebApplicationInitializer.class)
. Para casa initializer, seu método onStartup
será chamado.
Sendo assim é possível construir outras classes (além das próprias do Servlet Container) que representem initializers que serão chamados quando o server sobe. O Spring Mvc justamente já traz seu initializer padrão pra facilitar sua configuração programática, a classe AbstractAnnotationConfigDispatcherServletInitializer (se você for subindo pelas superclasses dela você chegara na classe pai que implementa a interface WebApplicationInitializer).
Visto isso quando criamos nossa classe filha de AbstractAnnotationConfigDispatcherServletInitializer, estamos adicionando mais um initializer ao contexto e sabemos que o mesmo será lido. O framework se encarregada (em algum onStartup de implementações em classes superiores) de chamar this.getRootConfigClasses() que será a nossa sobrescrita devolvendo algumas classes de configuração que definem beans que o framework vai instanciar e gerenciar daí pra frente.
No exemplo que você demonstrou a diferença deve estar no conteúdo das classes passadas, talvez o Configurador.class do segundo código deve estar provendo beans da JPA e do Spring ORM (módulo que integra o spring às soluções de ORM).
Espero ter ajudado no pensamento. Abraço!