Spring sem XML. É possível?

Sempre que falamos em trabalhar com Spring e colocá-lo em nossos projetos, sabemos que precisaremos configurar um bocado de XML para que o projeto possa ser usado e funcione corretamente. Desde integrações com os principais frameworks à beans do sistema, que podem receber configurações específicas no application-context.xml. Mas o que poucos desenvolvedores sabem é que desde a versão 3.0 do Spring já é possível trabalhar sem XML.

Os mais antigos com Spring, vão lembrar que a configuração era (quase que) completamente via XML e todas as classes do seu sistema era um bean configurado no arquivo xml.

Hoje em dia, esse tipo de configuração foi ficando cada vez mais “detestada”. A questão seria então, como usar Spring e não ter que manter “quilômetros” de XML em nossas aplicações?

Para começarmos nossa configuração, devemos criar uma classe que será a classe de configuração da nossa aplicação. Vamos criar a classe AppConfig, e para que o Spring saiba que essa será a classe que irá configurar nossa aplicação, vamos usar a annotation @Configuration.

@Configuration
public class AppConfig {

}

Mesmo com a classe anotada, ainda precisaremos informar ao Spring que essa é nossa classe de configuração. Como queremos ter apenas o web.xml de arquivo de configuração da aplicação, precisaremos informar ao Spring na inicialização do seu contexto, que nossa configuração será por annotation.

Para isso usaremos o parâmetro contextClass no web.xml. Conforme o código a seguir:

<init-param>
  <param-name>contextClass</param-name>
  <param-value>
    org.springframework.web.context.support.AnnotationConfigWebApplicationContext
  </param-value>
</init-param>

Além de informar isso precisamos também dizer qual é a classe anotada com @Configuration. O parâmetro é o mesmo que já usávamos para configurar o xml contextConfigLocation porém o value é a classe que usaremos como configuração padrão. No caso, o nome completo: br.com.caelum.mvc.AppConfig.

<init-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>br.com.caelum.mvc.AppConfig</param-value>
</init-param>

A configuração completa ficaria assim:

<servlet>
  <servlet-name>springmvc</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <init-param>
    <param-name>contextClass</param-name>
    <param-value>
      org.springframework.web.context.support.AnnotationConfigWebApplicationContext
    </param-value>
  </init-param>
  <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>br.com.caelum.mvc.AppConfig</param-value>
  </init-param>
</servlet>
<servlet-mapping>
  <servlet-name>springmvc</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

Agora que temos TODA a configuração XML que precisaremos, podemos começar a fazer as configurações específicas para o projeto.

Vamos informar ao Spring que estamos usando Spring MVC. No xml, faríamos <mvc:annotation-driver />. Essa mesma configuração deve ser feita em nossa classe AppConfig com a annotation @EnableWebMvc.

@EnableWebMvc
@Configuration
public class AppConfig {
  // outros métodos aqui
}

Assim como no XML existem configurações que são específicas para o SpringMVC. Essas configurações podem ser feitas em nossa classe quando estendemos a classe WebMvcConfigurerAdapter.

Essa classe nos possibilitará configurações comuns como <mvc:default-servlet-handler/>. Nossa classe ficaria assim:

@EnableWebMvc
@Configuration
public class AppConfig extends WebMvcConfigurerAdapter {
  @Override
  public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    configurer.enable();
  }
}

Com essas configurações, já conseguimos rodar a aplicação com SpringMVC. Porém para cada bean é necessário criar um método que retorna uma instância de nossos beans. Por exemplo, se queremos um bean chamado UsuarioDAO, teríamos que criar um método chamado usuarioDAO() anotado com @Bean como a seguir:

@EnableWebMvc
@Configuration
public class AppConfig {

  @Bean
  public UsuarioDAO usuarioDAO() {
    return new UsuarioDAO(); // instanciando o bean para o Spring injetar em algum lugar
  }

}

Da forma acima, passamos a ter muita configuração. Imagine quantos beans nossa aplicação terá e de quantos métodos apenas para que o Spring possa injetá-los precisaríamos?

Quando usamos XML, o Spring consegue injetar automaticamente sem termos que criar tags <bean />. Para isso, adicionamos a configuração . Com annotation também podemos fazer o mesmo, deixando para o Spring o trabalho de criar nossos beans. Para isso, colocaremos mais uma annotation na classe AppConfig chamada @ComponentScan e que possui uma propriedade basePackages onde você pode passar um pacote ou vários que serão escaneados. Nosso código ficará assim:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages={"br.com.caelum"})
public class AppConfig extends WebMvcConfigurerAdapter {

  // Métodos de configuração, nenhum bean da nossa app é necessário ...

}

Nossa aplicação com SpringMVC está quase pronta para rodar. Ainda precisamos informar como o Spring encontrará nossas páginas. Essa configuração é feita com um bean InternalResourceViewResolver informando as propriedades de prefix e suffix.

Vamos fazer essa mesma configuração. Quando configuramos no XML usamos um bean. Como já comentei, beans no XML viram métodos na configuração baseada em Java. Assim, devemos criar um método que retorne uma instância de InternalResourceViewResolver.

O que precisamos fazer na implementação é simples, instanciar essa classe e invocar os métodos setPrefix e setSuffix. Agora ficou fácil fazer o método completo.

@Bean
public InternalResourceViewResolver internalResourceViewResolver() {
  InternalResourceViewResolver resolver = new InternalResourceViewResolver();
  resolver.setPrefix("/WEB-INF/views/");
  resolver.setSuffix(".jsp");

  return resolver;
}

Com essa configuração, fechamos o mínimo necessário para rodar o SpringMVC completamente configurado via classe Java. Quando olhamos a classe final, vemos que o resultado é bem simples e justo.

O Spring configurado por annotation nos dá algumas vantagens:

  • Configuração compilável;
  • Auto-complete das IDE’s;
  • Instânciar um Bean de acordo com uma regra de usuário ou environment

 

E você, o que achou da configuração do Spring via Java? Quais outras vantagens você consegue ver usando configuração por annotation?

 

19 Comentários

  1. Rafael Ponte 05/08/2014 at 10:45 #

    Muito bom, Paulo.

    Hoje ainda eu prefiro usar o applicationContext.xml para configurações globais do container e que dificilmente mudam na aplicação, como pool de conexões, controle transacional e algumas outras. Qualquer mapeamento de bean e injeção de dependências é feito via anotações. Acho que a vantagem disso está mais relacionado com o conhecimento da equipe que já tem experiência com o XML do Spring e onde olhar em caso de problemas.

    Mas acho que a idéia de ter tudo configurado programaticamente via código Java (e algumas anotações) muito simples para quem nunca trabalhou com Spring, pois a pessoa não tem os vícios antigos e ainda pode usar o bom e velho ctrl+space ajuda muito.

    Enfim, abordagens diferentes que resolvem o mesmo problema.

    Parabéns pelo post, e espero que traga mais a tona assuntos relacionado ao Springzão de guerra, que eu sei que você curte muito!

  2. Tiago 06/08/2014 at 10:17 #

    Oi Paulo,

    Bacana o post, agora uma duvida, como ficaria a configuração do DataSource sem uso do xml?

  3. Paulo Alves 06/08/2014 at 14:29 #

    Fala Ponte,

    Obrigado, é isso aí, curto mesmo e sei que você também :). Como conversamos pelo CEJUG, eu também curto fazer no XML pelo costume, mas vale a pena experimentar e acho que vai gostar eim, eu estou curtindo muito.

    E aí Tiago, obrigado. Cada configuração de bean que era no XML agora vira um método na sua classe de configuração. E esse método deve retornar o DataSource e ser anotado com @Bean. Muito simples. Algo como abaixo:


    @Bean
    public DataSource dataSource( ) {
    BasicDataSource dataSource = new BasicDataSource();
    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    dataSource.setUrl("jdbc:mysql://localhost/db");
    dataSource.setUsername("root");
    dataSource.setPassword("");

    return dataSource;
    }

  4. Roberto 07/08/2014 at 11:22 #

    Ola Paulo,

    Ótimo post, eu ainda não conhecia essa forma de configuração.

    Como foi manifestado, a configuração via xml é mais comoda por já dominar o conhecimento, já a configuração via anotações eu achei bem clara e simples, vou testa-la.

  5. João Bortolozzo 07/08/2014 at 13:36 #

    Boa tarde Paulo.

    Seria legal também adicionar que no spring existe a possibilidade de configuração usando a interface WebApplicationInitializer para substituir o web.xml. Usando esta interface o projeto spring pode ser configurado com praticamente nenhum xml.

    Parabens pelo post. 🙂

  6. bruno 08/08/2014 at 14:57 #

    Conforme o João falou, implementando a WebApplicationInitializer não é necessário o uso do web.xml

  7. Fernando 08/08/2014 at 16:13 #

    Sim para remover todos xmls é só usar o que o João Bortolozzo falou

    public class MyWebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) {
    AnnotationConfigWebApplicationContext rootContext =
    new AnnotationConfigWebApplicationContext();
    rootContext.register(AppConfig.class);

    container.addListener(new ContextLoaderListener(rootContext));

    ServletRegistration.Dynamic dispatcher =
    container.addServlet(“dispatcher”, new DispatcherServlet(dispatcherContext));
    dispatcher.setLoadOnStartup(1);
    dispatcher.addMapping(“/”);
    }

    }

  8. Paulo Alves 08/08/2014 at 17:26 #

    Oi João, Bruno e Fernando

    Sim, também existe essa possibilidade. Não achei tão relevante para o post, uma vez que, em geral, sempre temos um web.xml. Outro motivo foi o foco do artigo que era substituir o XML do Spring. Mas é muito bom vocês já colocarem esse modelo, e o pessoal que quiser abolir o XML 100% já pode usar.

    Obrigado e abraço.

  9. Tiarê Balbi Bonamini 13/08/2014 at 10:16 #

    Parabéns pelo post!!

    Uma coisa legal de lembrar também é sobre o Spring Boot que vem trazendo uma série de configurações padrões já implementadas, simplificando a configuração do seu projeto. (Claro que é possível fazer um override nas configurações pre-definidas para que você possa configurar algo customizado).

    Mais um exemplo legal sobre a configuração do DataSource é a opção do “EmbeddedDatabaseBuilder”. Abaixo segue um exemplo.

    https://github.com/tiarebalbi/vote-no-filme/blob/master/src/main/java/com/tiarebalbi/config/DataContext.java#L44-L48

    Projeto exemplo:
    https://github.com/tiarebalbi/vote-no-filme/

    Ops.: Ele ainda possui 2 arquivos XML que são do Apache Tiles 3, que ainda não possui configuração via java.

  10. Stélio Moiane 15/08/2014 at 10:57 #

    Muito Bom, o post.

    Gostei

    Sucessos

  11. Matheus Felipe 27/08/2014 at 21:10 #

    Partindo dos meios de configuração sem XML, qual a vantagem de se utilizar WebApplicationInitializer ao invés do Spring Boot, onde qualquer tipo de configuração fica transparente para o desenvolvedor?

  12. Manoel 16/10/2014 at 22:37 #

    Olá Paulo tudo bom cara?, parabéns pelo post.

    sou muito muito novo mesmo no spring e isso me ajudou bastante realmente nao gosto de xml hehe

    gostaria de saber a respeito dessa linha no comentario anterior.
    BasicDataSource dataSource = new BasicDataSource();
    eu sei que com xml eu usario assim correto?

    <bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource"

    mas como seria a importação dessa classe ou ate mesmo eu crio ela? pq eu nao sei o seu funcionamento =)

    parabens mais uma vez!!!!

  13. Paulo Alves 21/10/2014 at 18:50 #

    Oi Manoel, creio que seja do mesmo jeito que eu comentei ali acima. Trocando apenas o DataSource que citei pelo DriverManagerDataSource que você usa.

    Faça alguns testes e dê uma olhada na documentação do Spring, geralmente ele mostra os dois modos.

    Abraço

  14. Fabio Pedrosa 25/11/2014 at 16:38 #

    Cara execelente artigo, estou usando aqui dessa maneira também, outro coisa muito interessante é o Spring Data, aqui a coisa fica seria abstração total da estrategia de persistência:http://docs.spring.io/spring-data/jpa/docs/1.7.1.RELEASE/reference/html/ onde abstraimos ate a camada dao de nossos projetos.

  15. Elvis 27/02/2015 at 10:55 #

    Isso aí, acho XML realmente um saco

  16. Ewerton 11/03/2016 at 08:41 #

    Se eu tenho um projeto Maven com três módulos: Dois “maven-archetype-quickstart” e um “maven-archetype-webapp”, em qual módulo eu crio a classe AppConfig ?

  17. Ewerton 11/03/2016 at 09:04 #

    Na verdade eu tenho um projeto Maven e mais dois módulos => UM “maven-archetype-quickstart” e UM “maven-archetype-webapp”, em qual módulo eu crio a classe AppConfig ?

  18. Ewerton 11/03/2016 at 09:27 #

    Eu tenho o projeto Maven => test-master
    Tenho o módulo “maven-archetype-quickstart” => nomeDaEmpresa-test-service
    E tenho o módulo “maven-archetype-webapp” => nomeDaEmpresa-test-web

    E os respectivos pom´s.xml para cada um dos três…

    Onde eu devo criar a classe AppConfig ?

  19. João Victor 21/03/2017 at 16:55 #

    Prezados,
    Estou trabalhando com spring há algum tempo, porém sempre realizei as configurações via XML. Recentemente, estou aplicando o spring security na minha aplicação e estou tendo algumas dificuldades para configura-lo. Uso o livro da casa do código Spring MVC – Domine o principal framework web java e os exemplos que eles usam são todos configurados na classe. Minha dúvida é, seria considerada uma má pratica eu ter configurações em xml e classe? Pois estou começando a pensar em usar classes para configuração do spring security.

Deixe uma resposta