Есть ли способ сканировать все @Component как аннотированный класс после Spring ApplicationContext Load - PullRequest
1 голос
/ 09 марта 2019

Я хочу добавить классы @Component в контейнер Spring после загрузки ApplicationContext. Но я не могу использовать BeanFactory. Поскольку я использую BeanFactory, я должен определить bean-компоненты для этих классов. Но я не могу определить это (если я не использую отражение). Потому что эти классы будут загружаться во время выполнения ClassLoader.

Например

@Component
public class Service {

    private final CustomerService customerService;
    private final OrderService orderService;
    private final PaymentService paymentService;

    @Autowired
    public Service(CustomerService customerService, OrderService orderService, PaymentService paymentService) {
        this.customerService = customerService;
        this.orderService = orderService;
        this.paymentService = paymentService;
    }
}

В этом примере Spring создает компонент для этого класса при вызове приложения. Нет необходимости определять bean с помощью @Bean. Но я хочу скомпилировать проекты Spring, загрузить их из другого проекта и добавить в Spring ApplicationContext. Так что я могу сделать это автоматически. В противном случае я должен создать бин с отражением во время выполнения. И если я использую рефлексию, я рекурсивно вызываю все зависимые классы.

Есть ли способ сделать это без создания bean-компонентов, использующих отражение во время выполнения.

Ответы [ 2 ]

2 голосов
/ 09 марта 2019

Я нашел решение.

    ConfigurableApplicationContext context = SpringApplication.run(EventServiceApplication.class, args);
    // Load class ...
    context.start();

Если мы запустим метод context.start () после загрузки класса, то Spring создаст @Component, подобный bean-компоненту класса, и поместит его в контейнер Spring.

Другойрешение (Это точное решение):

ConfigurableApplicationContext context = SpringApplication.run(EventServiceApplication.class, args);

List<Class<?>> classes = // load classes

classes
.stream()
.filter(clazz -> clazz.isAnnotationPresent(Component.class) || Arrays.stream(clazz.getAnnotations()).anyMatch(annotation -> annotation.annotationType().isAnnotationPresent(Component.class)))
.forEach(applicationContext::register);

После регистрации классов, возможно, один из загруженных вами классов помечен @Configuration и содержит @Bean аннотированных методов.Для регистрации этих @Bean методов.Вы должны использовать

ConfigurationClassPostProcessor configurationClassPostProcessor; // This class is autowireable. Spring has bean for this class at spring bean container.
configurationClassPostProcessor.processConfigBeanDefinitions(applicationContext.getDefaultListableBeanFactory())

Я нашел это решение в исходном коде Spring Framework

2 голосов
/ 09 марта 2019

Если я правильно понимаю: у вас есть классы, помеченные @Component, и вы хотите, чтобы Spring управлял их жизненным циклом?

Помогает ли это: https://springframework.guru/spring-component-scan/?@ComponentScan определенно или в конфигурации XML что-то вроде:

 <context:component-scan base-package="org.example"/>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...