【问题标题】:Is There Any Way To Scan All @Component like Annotated Class After Spring ApplicationContext LoadSpring ApplicationContext加载后,有什么方法可以扫描所有@Component(如带注释的类)
【发布时间】:2019-07-30 23:07:13
【问题描述】:

我想在 ApplicationContext 加载后将 @Component 类添加到 spring 容器中。但我不能使用 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 定义bean。但我想要的是编译 spring 项目并从另一个项目加载这些类并添加到 Spring ApplicationContext。所以我可以自动装配这些。否则我必须在运行时创建带有反射的bean。如果我使用反射,我会递归调用所有依赖类。

有没有办法在运行时不使用反射创建bean。

【问题讨论】:

  • 请将您的解决方案放在答案中并接受它,而不是将其编辑到您的问题中。

标签: java spring spring-boot


【解决方案1】:

如果我理解正确:您有一些标有 @Component 的类,并且您希望 Spring 管理它们的生命周期?

这有帮助吗:https://springframework.guru/spring-component-scan/ ? @ComponentScan 专门或在 XML 配置中类似:

 <context:component-scan base-package="org.example"/>

【讨论】:

  • “当应用程序启动时,Spring 需要信息来定位和注册所有 Spring 组件到应用程序上下文中”,在您的链接中。你是对的,但我需要在运行时注册 Spring 组件。换句话说,在应用程序上下文启动之后。我应该告诉在运行时加载类的应用程序启动后重新扫描组件
  • 我的错 - 这可能有用:stackoverflow.com/questions/4540713/…
【解决方案2】:

我找到了解决办法。

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

如果我们在加载类之后运行 context.start() 方法,spring 会像类 bean 一样创建 @Component 并放入 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 源代码中找到了这个解决方案

【讨论】:

    猜你喜欢
    • 2012-09-03
    • 2016-07-30
    • 1970-01-01
    • 1970-01-01
    • 2018-08-05
    • 2019-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多