I have some classes, with a custom annotation, that shouldn't be instantiated (abstract class, and it's just a subcomponents for a real beans). But on top of this classes, on runtime, on context initialization phase, I want to put extra beans into application context.
So, basically I need to scan classpath, process results, and introduce new beans into curent application context.
It seems that spring-mvc, spring-tasks and spring-integration are doing this (I tried to learn it from sources - no luck)
I found that I can create my own BeanFactoryPostProcessor
, scan classpath and call registerSingleton
for my custom bean. But I'm not sure that it's a good way for introducing new beans (seems that it's used only for postprocess of exising beans only). And I believe there are some Spring internal tools that I may reuse to simplify process.
What is a conventional way to introduce extra beans on Spring context initialization?
3.2. Beans are defined to be deployed in one of two modes: singleton or non-singleton.
Different Methods to Create a Spring BeanCreating Bean Inside an XML Configuration File (beans. xml) Using @Component Annotation. Using @Bean Annotation.
An alternative way to import the bean is to use the SpringApplicationBuilder's sources method. Since we have already imported the bean, the line is commented. @Autowired private TimeService timeService; Now that the bean is registered, we can inject it into the field.
There are at least two ways to include custom annotated classes as bean definitions:
<context:component-scan/>
for example:
<context:component-scan base-package="org.example">
<context:include-filter type="annotation" expression="org.example.Annotation"/>
</context:component-scan>
Then you can use a BeanPostProcessor
to instantiate them, for example:
public class CustomAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (beanClass.isAnnotationPresent(org.example.Annotation.class)) {
Object bean = createBeanInstance();
...
return bean:
}
return null;
}
}
Or use a BeanFactoryPostProcessor
to process the ScannedGenericBeanDefinitions
.
See AnnotationConfigUtils.registerAnnotationConfigProcessors()
for sample code of internal Spring annotation postprocessors.
Your observation is actually correct, BeanFactoryPostProcessor is one of the two ways Spring provides a mechanism to modify the bean definition/instances before making them available to the application(the other is using BeanPostProcessors)
You can absolutely use BeanFactoryPostProcessors to add/modify bean definitions, here is one sample from Spring Integration codebase that adds a errorChannel if not explicitly specified by a user, you can probably use a similar code for registering your new beans:
RootBeanDefinition errorChannelDef = new RootBeanDefinition();
errorChannelDef.setBeanClassName(IntegrationNamespaceUtils.BASE_PACKAGE
+ ".channel.PublishSubscribeChannel");
BeanDefinitionHolder errorChannelHolder = new BeanDefinitionHolder(errorChannelDef,
IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME);
BeanDefinitionReaderUtils.registerBeanDefinition(errorChannelHolder, registry);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With