Статьи

Имена инженера Spring и имена аргументов

Во время выполнения классы java не сохраняют имя параметров конструктора или метода, если только классы не скомпилированы с опциями отладки.

Это имеет некоторые интересные последствия для Spring Constructor Injection .

Рассмотрим следующий простой класс

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package dbg;
public class Person {
 
 private final String first;
 private final String last;
 private final Address address;
 
 public Person(String first, String last, Address address){
  this.first = first;
  this.last = last;
  this.address = address;
 }
 
 public String getFirst() {
  return first;
 }
 
 public String getLast() {
  return last;
 }
 
 public Address getAddress() {
  return address;
 }
}

и пример XML-файла конфигурации Spring bean:

1
2
3
<bean name='address1' class='dbg.Address' p:street1='street1' p:street2='street1' p:state='state1'/>
<bean name='person1' class='dbg.Person' c:address-ref='address1' c:last='Last1' c:first='First1'  ></bean>
<bean name='person2' class='dbg.Person' c:first='First2' c:address-ref='address1' c:last='Last2'   ></bean>

Здесь я использую пространство имен c для конструктора. Это терпит неудачу за исключением того, что типы аргументов являются неоднозначными — это потому, что первый аргумент является строкой, и поскольку его представление во время выполнения не имеет имени аргумента, Spring не может определить, следует ли заменить его именем или фамилией. В этом сценарии возможны несколько исправлений: 1. Использование внедрения на основе индекса, однако недостатком является то, что он очень многословен:

01
02
03
04
05
06
07
08
09
10
<bean name='person1' class='dbg.Person' >
 <constructor-arg value='First1'></constructor-arg>
 <constructor-arg value='Last1'></constructor-arg>
 <constructor-arg ref='address1'></constructor-arg>
</bean>
<bean name='person2' class='dbg.Person' >
 <constructor-arg value='First2'></constructor-arg>
 <constructor-arg value='Last2'></constructor-arg>
 <constructor-arg ref='address1'></constructor-arg>
</bean>

2. Чтобы компилировать с включенными символами отладки, это можно сделать, передав флаг -g или -g: var компилятору java — это обеспечит сохранение имен параметров в файле класса и исходной краткой конфигурации компонента с помощью c Пространство имен будет работать. 3. Аккуратное исправление — аннотировать конструктор с помощью @ConstructorProperties, который в основном предоставляет имена аргументов для Spring:

01
02
03
04
05
06
07
08
09
10
11
12
public class Person {
 
 private final String first;
 private final String last;
 private final Address address;
 
 @ConstructorProperties({'first','last','address'})
 public Person(String first, String last, Address address){
  this.first = first;
  this.last = last;
  this.address = address;
 }

Это работает с или без включенных параметров отладки. 4. Вероятно, лучшим решением будет просто использовать @Configuration для определения bean-компонентов:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
@Configuration
public static class TestConfiguration{
 
 @Bean
 public Address address1(){
  return new Address();
 }
 @Bean
 public Person person1(){
  return new Person('First1', 'Last1', address1());
 }
 @Bean
 public Person person2(){
  return new Person('First2', 'Last2', address1());
 }
 
}

Ссылка: имена Spring Constructor Injection и Argument от нашего партнера JCG Биджу Кунджуммена из блога all and sundry.