11

Is there a programmatic way to find out which Configuration class or xml file created a Spring bean? Instead of digging through the code to figure it out.

Arsaceus
  • 293
  • 2
  • 19
Glide
  • 20,235
  • 26
  • 86
  • 135
  • 1
    Once I had to debug similar issue. There is a phase where Spring reads bean definitions from various sources. You can put condition breakpoints in constructor of this bean definitions and catch a moment when its first created. Then you'll see the source by moving upper in the stacktrace. – AdamSkywalker Feb 03 '16 at 21:02
  • @AdamSkywalker Yeah I was hoping there would be an easier way than that. – Glide Feb 04 '16 at 01:05

1 Answers1

10

The following demonstrates how to obtain the source of the configuration using the bean name.

  1. Obtain the bean definition for the bean: ctx.getBeanDefinition("beanName")
  2. Invoke getResourceDescription().

Below is a working example which sets up a @Configuration based bean called 'a' defined in AppConfig, and an XML bean named "xmlBean" defined in SpringBeans.xml. In each case, the source @Configuration class, or xml file is displayed correctly.

Here is the java config class which sets up bean=a, and also loads XML config file SpringBeans.xml containing bean=xmlBean.

@Configuration
@ImportResource({"classpath:SpringBeans.xml"})
@ComponentScan(basePackages = "com.test.config")
public class AppConfig {

    @Bean
    public A a() {
        return new A();
    }

}

Here is the bean defined in SpringBeans.xml:

<bean id="xmlBean" class="com.test.HelloWorld">
    <property name="name" value="XML" />
</bean>

Here is simple code which uses getResourceDescription():

    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();

    ctx.register(AppConfig.class);
    ctx.refresh();

    BeanDefinition javaConfigBeanDefinition = ctx.getBeanDefinition("a");
    System.out.println("Creation class for a=" + javaConfigBeanDefinition.getResourceDescription());

    BeanDefinition xmlBeanDefinition = ctx.getBeanDefinition("xmlBean");
    System.out.println("Creation XML file for xmlBean=" + xmlBeanDefinition.getResourceDescription());

Output:

Creation class for a=com.test.config.AppConfig
Creation XML file for xmlBean=class path resource [SpringBeans.xml]

Probably a more practical way is to create a BeanDefinitionRegistryPostProcessor and request the information there:

@Component
public class FindBeanConfigLocation implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException {
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        BeanDefinition javaConfigBeanDefinition = registry.getBeanDefinition("a");
        System.out.println("Creation class for a=" + javaConfigBeanDefinition.getResourceDescription());

        BeanDefinition xmlBeanDefinition = registry.getBeanDefinition("xmlBean");
        System.out.println("Creation XML file for xmlBean=" + xmlBeanDefinition.getResourceDescription());
    }

}
Ian Mc
  • 5,656
  • 4
  • 18
  • 25
  • If you're have trouble obtaining the names of the beans it's possible to use `((GenericApplicationContext) ctx).getBeanDefinitionNames()`. Where `ctx` is `@Autowired public ApplicationContext ctx;` – Shane Gannon Sep 19 '22 at 18:54