Spring ApplicationContext 加载后,有没有办法扫描所有@Component 之类的带注释的类 [英] Is There Any Way To Scan All @Component like Annotated Class After Spring ApplicationContext Load

查看:58
本文介绍了Spring ApplicationContext 加载后,有没有办法扫描所有@Component 之类的带注释的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 ApplicationContext 加载后将 @Component 类添加到 spring 容器.但是我不能使用 BeanFactory.因为我正在使用 BeanFactory,所以我必须为这些类定义 bean.但我无法定义它(如果我不使用反射).因为这些类会在运行时由 ClassLoader 加载.

I want to add @Component classes to spring container after ApplicationContext load. But I cannot use BeanFactory. Because I'm using BeanFactory I have to define beans for these classes. But I cannot defined it(If I am not use reflection). Because these classes will load at runtime by 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.如果我使用反射,我会递归调用所有依赖类.

In this example Spring create bean for this class while application invoking. There is no need to define bean with @Bean. But what I want is compile spring projects and load those clasess from another project and add to Spring ApplicationContext. So i can autowire these. Otherwise I have to create bean with reflection at runtime. And if I use reflection, I have invoke all dependent class recursively.

有没有什么办法可以不用在运行时使用反射创建 bean.

Is there any way do it without create beans using reflection at runtime.

推荐答案

我找到了解决方案.

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

如果我们在加载类之后运行 context.start() 方法,spring 会像类 bean 一样创建 @Component 并放入 spring 容器.

If we run context.start() method after load class, spring create @Component like class beans and put to spring container.

另一种解决方案(这是确切的解决方案):

Another solution (This is exact solution):

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 方法.你应该使用

After register the classes, maybe one of your loaded class annoteded with @Configuration and it contains @Bean annotated methods. For register those @Bean methods. You should use

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

我在 Spring Framework 源代码中找到了这个解决方案

I found this solution at Spring Framework source code

这篇关于Spring ApplicationContext 加载后,有没有办法扫描所有@Component 之类的带注释的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆