1

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.

For example

@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;
    }
}

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.

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

1
  • Please put your solution in an answer and accept it, rather than editing it into your question. Commented Mar 9, 2019 at 0:36

2 Answers 2

2

If I understand things correctly: you have some classes that are marked with @Component and you want Spring to manage their lifecycle?

Does this help: https://springframework.guru/spring-component-scan/ ? @ComponentScan specifically or in XML config something like:

 <context:component-scan base-package="org.example"/>
Sign up to request clarification or add additional context in comments.

2 Comments

"Spring needs the information to locate and register all the Spring components with the application context when the application starts", At your link. You are right but I need to register Spring components at runtime. In other word, after application context start. I should tell to spring re-scan components after application start for loaded class at runtime
My bad - this might be useful: stackoverflow.com/questions/4540713/…
2

I found a solution.

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

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);

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())

I found this solution at Spring Framework source code

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.