Skip to content

Detecting transitive bean dependency usage #36153

@geoffwa

Description

@geoffwa

Hi Spring Team,

I work in a large monorepo containing multiple modules maintained by different teams exposing different interfaces. A module is a @Configuration class that creates beans implementing a common interface which is typically configured through properties or the environment the consuming application is running in.

One issue we have with this is managing dependences; imagine something like the following:

class Beans {
@Configuration
  @Import({
      B.class,
      D.class
  })
  public static class A {
    @Bean(name="aBean")
    public Object aBean(
        @Named("bBean") String bBean,
        @Named("cBean") String cBean,
        @Named("dBean") String dBean
    ) {
      return "ABean" + bBean + cBean + dBean;
    }
  }

  @Configuration
  @Import({C.class})
  public static class B {
    @Bean(name="bBean")
    public Object bBean() {
      return "BBean";
    }
  }

  @Configuration
  public static class C {
    @Bean(name="cBean")
    public Object cBean() {
      return "CBean";
    }
  }

  @Configuration
  public static class D {
    @Bean(name="dBean")
    public Object dBean() {
      return "DBean";
    }
  }
}

In this example aBean depends upon bBean, cBean and dBean but its parent @Configuration only imports bBean and dBean directly - cBean is imported transitively via the B module.

To make this easier to maintain (at least in our case) it'd be better if A pulled in C directly via @Import.

I'd like to build a helper library to detect this when the configuration is loaded and if transitive dependencies are detected the library could throw an exception or log a warning message.

Looking through the code that loads @Configuration classes directly this isn't particularly easy; I can pull registered bean definitions out of my DefaultListableBeanFactory after they're registered but I have to do a bunch of work to figure out where they and their dependencies came from. There's the ConfigurationClassPostProcessor/ConfigurationClassParser pair, but the former does all its work in processConfigBeanDefinitions and there's not a good way to observe the ConfigurationClass instances as they're parsed.

Do you have any recommendations on how to proceed here? I'm doing all of this work in spring 6.2.15 - if there are better interfaces in newer versions of the spring framework I can take a look.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions