Is it possible to register all classes within a package as Spring beans Is it possible to register all classes within a package as Spring beans spring spring

Is it possible to register all classes within a package as Spring beans


ClassPathBeanDefinitionScanner is all you need.

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());    }}

You can pass custom logic in include filter if you want. In current version every class in the provided package will be included as a bean.

But it is impossible to build a right dependency structure on your classes automagically, it really depends on the scope you want. You need to do it by your hands.


I'd do pretty much the same thing that Roman did, only I'd do it at build time, not at runtime, using code generation. The rationale here is that I strongly prefer magic to happen at build time to magic that happens at deploy time.

In the simplest version, write a main method that scans the package (instead of reflections api, I'm using Guava's ClassPath scanner) and creates a @Bean method for every class it finds.

For the Code generation, I'd use 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"));  }}


You can try to use your own BeanDefinitionRegistryPostProcessor

@Componentpublic class CustomBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {  @Override  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {    Reflections reflections = new Reflections("my.package.prefix", new SubTypesScanner(false));    Set<Class<? extends Object>> 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  }}

See sample project at https://github.com/sandarkin/so-q37548350