如何从ConfigurableApplicationContext中获取Bean包?

huangapple go评论58阅读模式
英文:

How to get the Bean package from ConfigurableApplicationContext

问题

使用类似于ConfigurableApplicationContext的接口,可以检索在Spring DI容器中运行的Bean列表,但我想知道哪些Bean来自用户空间,哪些Bean来自Spring Boot / Spring Boot Starters。

@TestConfiguration
static class BeanInventoryConfiguration {

    @Autowired
    private ConfigurableApplicationContext applicationContext;

    record BeanInventory(List<String> beans) {}

    @Bean
    public BeanInventory getBeanInventory(ConfigurableApplicationContext applicationContext) {
        String[] allBeanNames = applicationContext.getBeanDefinitionNames();
        return new BeanInventory(Arrays.stream(allBeanNames).toList());
    }
}

是否存在一种方法可以返回Bean所在的包?
如果我知道包,我可以轻松地进行筛选。

在Spring的Javadoc中,我没有找到一种方法:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ConfigurableApplicationContext.html

非常感谢您的提前帮助。

POC: https://github.com/jabrena/spring-boot-http-client-poc/blob/main/src/test/java/ms/info/ms/BeanInventoryTests.java

英文:

Using a interface like ConfigurableApplicationContext, it is possible to retrieve the list of Beans running in the Spring DI container, but I would like to know what Beans come from the User Space and what Beans comes from the Spring Boot / Spring Boot Starters.

@TestConfiguration
static class BeanInventoryConfiguration {

    @Autowired
    private ConfigurableApplicationContext applicationContext;

    record BeanInventory(List<String> beans) {}

    @Bean
    public BeanInventory getBeanInventory(ConfigurableApplicationContext applicationContext) {
        String[] allBeanNames = applicationContext.getBeanDefinitionNames();
        return new BeanInventory(Arrays.stream(allBeanNames).toList());
    }
}

Does exist a way to return the package where the Bean is located?
If I know the package, I could filter in a easy way.

Reviewing the Javadoc from Spring, I didnt find a way:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ConfigurableApplicationContext.html

Many thanks in advance

POC: https://github.com/jabrena/spring-boot-http-client-poc/blob/main/src/test/java/ms/info/ms/BeanInventoryTests.java

答案1

得分: 0

我找到了一个解决方案:

@TestConfiguration
public class BeanInventory {

    @Autowired
    private ConfigurableApplicationContext applicationContext;

    public record BeanInfo(String name, String pkg) {}
    private final List<BeanInfo> beans = new ArrayList<>();

    @PostConstruct
    private void after() {

        final String[] beanNames = applicationContext.getBeanDefinitionNames();
        for (String beanName : beanNames) {
            final Object beanObject = applicationContext.getBean(beanName);
            Class<?> targetClass = AopUtils.getTargetClass(beanObject);

            if (AopUtils.isJdkDynamicProxy(beanObject)) {
                Class<?>[] proxiedInterfaces = AopProxyUtils.proxiedUserInterfaces(beanObject);
                Assert.isTrue(proxiedInterfaces.length == 1, "Only one proxied interface expected");
                targetClass = proxiedInterfaces[0];
            }

            beans.add(new BeanInfo(beanName, targetClass.getPackageName()));
        }
    }

    public List<BeanInfo> getBeans() {
        return beans;
    }
}

更多信息请参阅:
https://github.com/spring-projects/spring-framework/issues/29973#event-8527246281

注:非常感谢Simon Basle。

英文:

I found a solution for it:

@TestConfiguration
public class BeanInventory {

	@Autowired
	private ConfigurableApplicationContext applicationContext;

	public record BeanInfo(String name, String pkg) {}
	private final List<BeanInfo> beans = new ArrayList<>();

	@PostConstruct
	private void after() {

		final String[] beanNames = applicationContext.getBeanDefinitionNames();
		for (String beanName : beanNames) {
			final Object beanObject = applicationContext.getBean(beanName);
			Class<?> targetClass = AopUtils.getTargetClass(beanObject);

			if (AopUtils.isJdkDynamicProxy(beanObject)) {
				Class<?>[] proxiedInterfaces = AopProxyUtils.proxiedUserInterfaces(beanObject);
				Assert.isTrue(proxiedInterfaces.length == 1, "Only one proxied interface expected");
				targetClass = proxiedInterfaces[0];
			}

			beans.add(new BeanInfo(beanName, targetClass.getPackageName()));
		}
	}

	public List<BeanInfo> getBeans() {
		return beans;
	}

}

Further information here:
https://github.com/spring-projects/spring-framework/issues/29973#event-8527246281

Note: Many thanks to Simon Basle

huangapple
  • 本文由 发表于 2023年2月13日 22:46:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/75437426.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定