Back-End

8 fev, 2013

Utilizando os perfis de Spring e a configuração Java

Publicidade

Neste artigo, introduzi os perfis do Spring 3.1, expliquei ambos os casos de negócio para usá-los e demonstrei o uso deles com arquivos de configuração do Spring XML. Parece, no entanto, que boa parte dos desenvolvedores prefere usar a configuração do aplicativo baseado em Java do Spring, e aí o Spring designou um modo de usar os perfis com a sua anotação existente @Configuration.

Vou demonstrar os perfis e a anotação @Configuration usando a classe Person do meu artigo anterior. Esta é uma classe bean simples, cujas propriedades variam dependendo de qual perfil está ativo.

public class Person {

private final String firstName;
private final String lastName;
private final int age;

public Person(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}

public String getFirstName() {
return firstName;
}

public String getLastName() {
return lastName;
}

public int getAge() {
return age;
}
}

Lembre-se de que os caras do Spring recomendam que os perfis do Spring só devem ser usados quando você precisa carregar diferentes tipos ou conjuntos de classes e que para a definição de propriedades você deve continuar usando o PropertyPlaceholderConfigurer. A razão de eu estar quebrando as regras é que eu quero tentar escrever o código mais simples possível para demonstrar os perfis e a configuração Java.

No coração do uso de perfis do Spring com configuração Java está a nova anotação do Spring @Profile. Ela é usada anexada a um nome de perfil para uma anotação @Configuration. Ela usa um único parâmetro que pode ser utilizado de duas maneiras. Primeiro para anexar um único perfil para uma anotação @Configuration:

@Profile("test1")

e, segundo, para anexar vários perfis:

@Profile({ "test1", "test2" })

Mais uma vez, vou definir dois perfis, “test1” e “test2”, e associar cada um a um arquivo de configuração. Primeiro, o “test1”:

@Configuration
@Profile("test1")
public class Test1ProfileConfig {@Bean
public Person employee() {

return new Person("John", "Smith", 55);
}
}

E depois o “test2”:

@Configuration
@Profile("test2")
public class Test2ProfileConfig {

@Bean
public Person employee() {

return new Person("Fred", "Williams", 22);
}
}

Perceba que no código acima eu estou criando um bean Person com uma id efetivo de employee (este é o nome do método) que retorna diferentes valores de propriedade em cada perfil.

Observe também que o @Profile está marcado como:

@Target(value=TYPE)

… o que significa que ele só pode ser colocado ao lado da anotação @Configuration.

Anexando um @Profile a um @Configuration, a próxima coisa a fazer é ativar o seu @Profile selecionado. Isso utiliza exatamente os mesmos princípios e as mesmas técnicas que eu descrevi neste artigo e, novamente, a meu ver, a técnica de ativação mais útil é usar a propriedade de sistema “spring.profiles.active”.

@Test
public void testProfileActiveUsingSystemProperties() {

System.setProperty("spring.profiles.active", "test1");
ApplicationContext ctx = new ClassPathXmlApplicationContext("profiles-config.xml");

Person person = ctx.getBean("employee", Person.class);
String firstName = person.getFirstName();
assertEquals("John", firstName);
}

Obviamente, você não vai querer fazer coisas “hard code” como fiz acima e manter as melhores práticas geralmente significa manter as propriedades de configuração do sistema separadas do seu aplicativo. Isso te dá a opção de usar um argumento de linha de comando simples, como:

-Dspring.profiles.active="test1"

… ou adicionando

# Setting a property value
spring.profiles.active=test1

a catalina.properties do Tomcat.

Então, isto é tudo: você cria seus perfis do Spring anotando uma an @Configuration com uma @Profile e então ativa o perfil que deseja usar, definindo a propriedade do sistema spring.profiles.active ao nome do seu profile.

Como de costume, os caras do Spring não só limitam você a usar as propriedades do sistema para ativar perfis, você pode fazer coisas programaticamente (nem sei se existe essa palavra, mas era a mais próxima). Por exemplo, o código a seguir cria um AnnotationConfigApplicationContext e depois usa um objeto Environment para ativar o perfil “test1” antes de registrar nossas classes @Configuration.

@Test
public void testAnnotationConfigApplicationContextThatWorks() {

// Can register a list of config classes
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("test1");
ctx.register(Test1ProfileConfig.class, Test2ProfileConfig.class);
ctx.refresh();

Person person = ctx.getBean("employee", Person.class);
String firstName = person.getFirstName();
assertEquals("John", firstName);
}

Tudo isso é lindo e bom, mas cuidado! Você precisa chamar os métodos de AnnotationConfigApplicationContext na ordem certa. Por exemplo, se você registrar suas classes @Configuration antes de especificar o seu perfil, então você vai ter um IllegalStateException.

@Test(expected = IllegalStateException.class)
public void testAnnotationConfigApplicationContextThatFails() {

// Can register a list of config classes
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
Test1ProfileConfig.class, Test2ProfileConfig.class);
ctx.getEnvironment().setActiveProfiles("test1");
ctx.refresh();

Person person = ctx.getBean("employee", Person.class);
String firstName = person.getFirstName();
assertEquals("John", firstName);
}

Antes de encerrar o artigo de hoje, o código abaixo demonstra a capacidade de anexar múltiplos @Profile para uma anotação @Configuration.

@Configuration
@Profile({ "test1", "test2" })
public class MulitpleProfileConfig {

@Bean
public Person tourDeFranceWinner() {

return new Person("Bradley", "Wiggins", 32);
}
}

 

@Test
public void testMulipleAssignedProfilesUsingSystemProperties() {

System.setProperty("spring.profiles.active", "test1");
ApplicationContext ctx = new ClassPathXmlApplicationContext("profiles-config.xml");

Person person = ctx.getBean("tourDeFranceWinner", Person.class);
String firstName = person.getFirstName();
assertEquals("Bradley", firstName);

System.setProperty("spring.profiles.active", "test2");
ctx = new ClassPathXmlApplicationContext("profiles-config.xml");

person = ctx.getBean("tourDeFranceWinner", Person.class);
firstName = person.getFirstName();
assertEquals("Bradley", firstName);
}

No código acima, o vencedor do Tour de France 2012, Bradley Wiggins, aparece tanto no perfil “test1” quanto no  “test2”.

***

Texto original disponível em http://www.captaindebug.com/2012/08/using-spring-profiles-and-java.html#.UPdhKif7KSo