Spring ApplicationContext 加载后,有没有办法扫描所有@Component 之类的带注释的类 [英] Is There Any Way To Scan All @Component like Annotated Class After Spring ApplicationContext Load
问题描述
我想在 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屋!