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

pcz*_*eus 6 java groovy spring dependency-injection spring-boot

我熟悉基于Springs Java的配置选项,包括注册Spring bean的注释的使用@Component@Configuration结合@Bean注释.

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

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

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

Ser*_*rCe 8

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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


Sea*_*oyd 7

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

在最简单的版本中,编写一个扫描包的主方法(而不是反射api,我正在使用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"));

  }
}
Run Code Online (Sandbox Code Playgroud)