Статьи

Профили Spring и конфигурация Java

В моем последнем блоге были представлены профили Spring 3.1, объяснены причины их использования и продемонстрировано их использование с файлами конфигурации Spring XML. Однако, похоже, что многие разработчики предпочитают использовать конфигурацию приложений Spring на Java, и поэтому Spring разработала способ использования профилей с существующей аннотацией @Configuration .

Я собираюсь продемонстрировать профили и аннотацию @Configuration с помощью класса Person из моего предыдущего блога. Это простой класс компонентов, свойства которого различаются в зависимости от того, какой профиль активен.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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;
  }
}

Помните, что ребята из Spring рекомендуют использовать профили Spring только тогда, когда вам нужно загрузить разные типы или наборы классов, и что для установки свойств вы должны продолжать использовать PropertyPlaceholderConfigurer . Причина, по которой я нарушаю правила, заключается в том, что я хочу попробовать написать самый простой код, демонстрирующий профили и конфигурацию Java.

В основе использования профилей Spring с настройкой Java лежит новая аннотация Spring @Profile . Аннотация @Profile используется для прикрепления имени профиля к примечанию @Configuration . Он принимает один параметр, который можно использовать двумя способами. Во-первых, чтобы прикрепить один профиль к аннотации @Configuration :

1
@Profile("test1")

и во-вторых, чтобы прикрепить несколько профилей:

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

Опять же, я собираюсь определить два профиля «test1» и «test2» и связать каждый из них с файлом конфигурации. Сначала «test1»:

01
02
03
04
05
06
07
08
09
10
@Configuration
@Profile("test1")
public class Test1ProfileConfig {
  
  @Bean
  public Person employee() {
  
    return new Person("John", "Smith", 55);
  }
}

… А затем «test2»:

01
02
03
04
05
06
07
08
09
10
@Configuration
@Profile("test2")
public class Test2ProfileConfig {
  
  @Bean
  public Person employee() {
  
    return new Person("Fred", "Williams", 22);
  }
}

В приведенном выше коде вы можете видеть, что я создаю bean-компонент Person с эффективным id сотрудника (это из имени метода), который возвращает разные значения свойств в каждом профиле.

Также обратите внимание, что @Profile помечен как:

1
@Target(value=TYPE)

… Что означает, что его можно поместить только рядом с аннотацией @Configuration .

Прикрепив @Profile к @Configuration , вы должны активировать выбранный @Profile . При этом используются те же принципы и методы, которые я описал в своем последнем блоге, и, опять же, на мой взгляд, наиболее полезный метод активации заключается в использовании системного свойства «spring.profiles.active».

01
02
03
04
05
06
07
08
09
10
@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);
}

Очевидно, что вы не захотите жестко кодировать вещи, как я делал выше, и наилучшая практика обычно подразумевает сохранение конфигурации системных свойств отдельно от вашего приложения. Это дает вам возможность использовать простой аргумент командной строки, такой как:

1
-Dspring.profiles.active="test1"

… или добавив

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

к кошке Tomcat's.properties

Итак, это все, что нужно сделать: вы создаете свои профили Spring, аннотируя @Configuration аннотацией @Profile, а затем переключая профиль, который вы хотите использовать, устанавливая системное свойство spring.profiles.active на имя вашего профиля. ,

Как обычно, ребята в Spring не просто ограничивают использование системных свойств для активации профилей, вы можете делать это программно. Например, следующий код создает AnnotationConfigApplicationContext, а затем использует объект Environment для активации профиля «test1» перед регистрацией наших классов @Configuration .

01
02
03
04
05
06
07
08
09
10
11
12
13
@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);
}

Это все хорошо, но будьте осторожны, вам нужно вызывать методы AnnotationConfigApplicationContext в правильном порядке. Например, если вы зарегистрируете свои классы @Configuration до того, как укажете свой профиль, вы получите исключение IllegalStateException .

01
02
03
04
05
06
07
08
09
10
11
12
13
@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);
}

Перед закрытием сегодняшнего блога приведенный ниже код демонстрирует возможность прикрепления нескольких @Profiles к аннотации @Configuration .

01
02
03
04
05
06
07
08
09
10
@Configuration
@Profile({ "test1", "test2" })
public class MulitpleProfileConfig {
  
  @Bean
  public Person tourDeFranceWinner() {
  
    return new Person("Bradley", "Wiggins", 32);
  }
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
@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);
}

В приведенном выше коде победитель Тур де Франс 2012 года Брэдли Уиггинс появляется в профилях «test1» и «test2».  

Ссылка: Spring, Enterprise Java от нашего партнера по JCG Роджера Хьюза в блоге Captain Debug’s Blog .