I have a situation where I want to look for interfaces annotated with a given annotation, then check if a matching implementation is available. If not, I want to make a bean available that is actually a JDK proxy of the interface, essentially exactly what:
@ConditionalOnMissingBean
would do, except without writing a factory method for each of those.
I have code that is working "sometimes" - it seems extremely sensitive to the classloader structure, specifically, wether classes are loaded from a springboot fat jar (works) or wether some part is loaded from a separate classpath entry (doesnt work, mostly).
here is what I am doing:
@Service
@Order(value = Ordered.LOWEST_PRECEDENCE)
public class RemotingImportService implements BeanFactoryPostProcessor {
private static Log log = LogFactory.getLog(RemotingExportService.class);
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// scan classpath with classgraph, then:
for (ClassInfo classInfo : scanResult.getClassesWithAnnotation(MyAnnotation.class.getCanonicalName())) {
Class c = Class.forName(classInfo.getName());
if(beanFactory.getBeanNamesForType(c).length > 0) {
implFound = true;
log.info(c.getName()+" already has an implementation ... skipping");
continue;
}
// create proxy, then:
GenericBeanDefinition bdService = new GenericBeanDefinition();
bdService.setBeanClassName(classInfo.getName());
bdService.setInstanceSupplier(new ProxySupplier(proxy));
bdService.setLazyInit(true);
((DefaultListableBeanFactory) beanFactory).registerBeanDefinition(classInfo.getName(), bdService);
log.info(c.getName()+" has NO implementation ... proxy registerd");
}
in some cases, it seems that the beanfactory isn't finished, and
beanFactory.getBeanNamesForType()
returns an empty list, although it does find beans for that type later. i am aware that messing with this is probably not ideal - but it would be nice to find a solution that plays nice with spring boot.
any suggestions on how to solve this? a way to mark a bean definition as "ConditionalOnMissingBean" would also be great.