是否可以将包中的所有类注册为Spring bean

我熟悉基于Springs Java的配置选项,包括使用@Component@Configuration以及@Bean注释来注册Spring bean。

但是,在将一个体面的项目转换为Spring时,系统地触摸项目中的所有类并使用@Configuration @Bean更新或使用@Component注释每个类可能非常耗费人力。 我们有一个很大的Groovy项目要转换,我想简化这个过程。

我的问题: Spring中是否提供了一个工具,允许您告诉Spring在特定包中自动配置所有有效的bean候选类?

如果没有,还有哪些其他选择?

ClassPathBeanDefinitionScanner就是您所需要的。

 public class Main { public static void main(String[] args) { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, false); scanner.addIncludeFilter((metadataReader, metadataReaderFactory) -> true); scanner.scan("net.company.name"); context.refresh(); A a = context.getBean(A.class); System.out.println(a.toString()); } } 

如果需要,您可以在包含filter中传递自定义逻辑。 在当前版本中,提供的包中的每个类都将作为bean包含在内。

但是不可能在类上自动构建正确的依赖结构,它实际上取决于你想要的范围。 你需要亲自动手。

我做的几乎和Roman一样,只是我在构建时,而不是在运行时,使用代码生成。 这里的基本原理是我非常喜欢魔法在构建时发生在部署时发生的魔法。

在最简单的版本中,编写一个扫描包的main方法(而不是reflectionapi,我正在使用Guava的ClassPath扫描程序)并为它找到的每个类创建一个@Bean方法。

对于代码生成,我使用JCodeModel :

 public class PackageBeanGenerator { public static void main(String[] args) throws Exception { String packageName = args[0]; JCodeModel codeModel = new JCodeModel(); // create class definition JDefinedClass springConfig = codeModel._package(packageName)._class("SpringConfig"); springConfig.annotate(Configuration.class); for (ClassPath.ClassInfo classInfo : ClassPath.from( PackageBeanGenerator.class.getClassLoader() ).getTopLevelClasses(packageName)) { Class type = classInfo.load(); String beanName = CaseFormat.UPPER_CAMEL.to( CaseFormat.LOWER_CAMEL, type.getSimpleName()); JMethod beanMethod = springConfig.method(JMod.PUBLIC, type, beanName); beanMethod.annotate(Bean.class); beanMethod.body()._return(JExpr._new(codeModel._ref(type))); } // write class to file codeModel.build(new File("/path/to/output/folder")); } } 

您可以尝试使用自己的BeanDefinitionRegistryPostProcessor

 @Component public class CustomBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { Reflections reflections = new Reflections("my.package.prefix", new SubTypesScanner(false)); Set> allClasses = reflections.getSubTypesOf(Object.class); for (Class clazz : allClasses) { GenericBeanDefinition gbd = new GenericBeanDefinition(); gbd.setBeanClass(clazz); gbd.setAttribute("attributeName", "attributeValue"); registry.registerBeanDefinition(clazz.getSimpleName() + "_Bean", gbd); } } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { // Custom post process the existing bean definitions } } 

请参阅https://github.com/sandarkin/so-q37548350上的示例项目

冒着听起来原始的风险,为什么不在IDE中进行简单的查找和替换(例如在包中搜索“public class”并替换为“@Component public class”)? 这应该比以编程方式做任何事情要快得多。