Affects: \<5.2.11.RELEASE>
For enhancements, provide context and describe the problem. Some of my java lib not imported by maven, and I want to load it by CustomClassLoader, and scan java lib class to register spring bean.
I found to implements ImportBeanDefinitionRegistrar and @Import it will good for me. some code like this:
@Configuration(proxyBeanMethods = false)
static class PluginBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
ClassLoader pluginClassLoader = Plugin.getPluginClassLoader();
//scanner
ClassPathBeanDefinitionScanner scanner =
new PluginClassPathBeanDefinitionScanner(registry, true, applicationContext.getEnvironment(),
new DefaultResourceLoader(pluginClassLoader));
BeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(Plugin.getPluginClass()).getBeanDefinition();
Set<String> basePackages = new LinkedHashSet<>();
basePackages.add(ClassUtils.getPackageName(Plugin.getPluginClass()));
scanner.addExcludeFilter(new AssignableTypeFilter(TypeExcludeFilter.class));
scanner.addExcludeFilter(new AssignableTypeFilter(AutoConfigurationExcludeFilter.class));
scanner.addExcludeFilter(new AnnotationTypeFilter(SpringBootApplication.class));
scanner.scan(StringUtils.toStringArray(basePackages));
}
}
and PluginClassPathBeanDefinitionScanner will load class Resource into BeanDefinition
public class PluginClassPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {
@SneakyThrows
@Override
public int scan(String... basePackages) {
int beanCountAtScanStart = this.getRegistry().getBeanDefinitionCount();
Set<BeanDefinitionHolder> scanBds = doScan(basePackages);
loadBeanResource(scanBds);
return (this.getRegistry().getBeanDefinitionCount() - beanCountAtScanStart);
}
private void loadBeanResource(Set<BeanDefinitionHolder> bdhs) throws IOException {
for (BeanDefinitionHolder bdh : bdhs) {
BeanDefinition bd = bdh.getBeanDefinition();
if (bd instanceof AbstractBeanDefinition) {
//load class by this resource loader
MetadataReader meta = this.getMetadataReaderFactory().getMetadataReader(Objects.requireNonNull(bd.getBeanClassName()));
((AbstractBeanDefinition) bd).setResource(meta.getResource());
}
}
}
}
unfortunately SpringContext org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>)
will parse those loaded BeanDefinitions with SpringContext org.springframework.context.annotation.ConfigurationClassParser#metadataReaderFactory
and absolutely ClassNotFound Exception.
What if: * first use BeanDefinition Resource or BeanClass if it is not null * or load resource or bean class by SpringContext ResourceLoad(or MetadataReaderFactory)
If there are another way to solve my problem, please let me know, thanks!!!