ввод поля без конструктора или установщиков

#java #spring

Вопрос:

У меня есть java-класс jar, который использует инъекцию поля spring, с пустым конструктором

 public JarClass {

@Autowired
private JarField jarfield;

public JarClass() {}

}
 

Я хотел бы импортировать этот компонент в другой проект с инициализированным полем jarField

до сих пор я создавал класс в другом проекте, подобном этому

 @Configuration
public class Config {


@Bean
public JarField jarField() {
return new JarField();
}

@Bean
public JarClass jarClass() {
return new JarClass();
}

}
 

если бы у меня был конструктор для внедрения зависимостей внутри JarClass, например

 public JarClass {

private JarField jarfield;

this.jarField = jarField;

public JarClass(JarField jarfield) {

}
 

Я мог бы легко установить поле таким образом :

 @Configuration
public class Config {


@Bean
public JarField jarField() {
return new JarField();
}

@Bean
public JarClass jarClass(@Bean JarField jarField) {
return new JarClass(jarField);
}

}
 

}

Но у меня нет для этого ни конструктора, ни сеттера.

Есть идея сделать мой JarField ненулевым без изменения JarClass удаленного класса ?

}

Ответ №1:

 public JarClass {

@Autowired
private JarField jarfield;

public JarClass() {}

}
 

Приведенный выше класс приносит @Autowired , поэтому он также должен быть пружинным бобом какого-либо типа @Component , @Service … Он не может быть создан с @Bean помощью другого модуля, так как у него будет та же проблема с впрыском, с которой вы сталкиваетесь сейчас. Таким образом, мы в основном уверены, что у него есть какой-то тип аннотации, такой как @Component

Исходя из этого, вам вообще не нужно предоставлять

 @Bean
public JarClass jarClass(@Bean JarField jarField) {
return new JarClass...
}
 

Обеспечьте только необходимую зависимость

 @Bean
public JarField jarField() {
return new JarField();
}
 

и адаптируйте отсканированный пакет, чтобы включить пакет, в котором существует класс JarClass.

Затем весна сделает это волшебно, и она предоставит вам боб JarClass со всеми зависимостями.

Ответ №2:

Вы можете инициализировать компонент за другим компонентом, используя аннотацию dependsOn.

Кроме того, вам нужно инициализировать компонент вручную, вот так:

 @Configuration
public class Config {

  @Autowired
  private ApplicationContext applicationContext;    

  @Bean
  public JarField jarField() {
    return new JarField();
  }

  @Bean
  @DependsOn({"jarField"})
  public JarClass jarClass() {
    JarClass jarClass = new JarClass();
    AutowireCapableBeanFactory factory = applicationContext.getAutowireCapableBeanFactory();
    factory.autowireBean( jarClass );
    return jarClass;
  }

}
 

Метод autowireBean будет обрабатывать поля и методы @Autowired. Если вам также необходимо вызвать постобработку (@PostConstruct и любые определенные BeanPostProcessors), также используйте:

 factory.initializeBean( jarClass, "jarClass" );
 

Ответ №3:

Изменить:

 public JarClass {

private JarField jarfield;

this.jarField = jarField;

public JarClass(JarField jarfield) {

}
 

В это:

 public JarClass {
   private final JarField jarfield;
   
   @Autowired
   public JarClass(JarField jarfield) {
       this.jarField = jarField;
   }
}
 

Комментарии:

1. Никакие модификации jarClass невозможны

2. Ну, вы можете создать новый класс, который расширит ваш JarClass и исправит нулевую часть.