spring - 使用 BeanDefinitionRegistryPostProcessor 创建 N 个 bean
问题描述
我正在尝试使用动态创建N个 bean BeanDefinitionRegistryPostProcessor
。基于这个问题,我选择使用BeanDefinitionRegistryPostProcessor
我的用例。
我在我的中定义了以下内容application.yml
:
app:
downstream-services:
rest:
jsonPlaceHolder:
url: https://jsonplaceholder.typicode.com/todos
api-type: io.mateo.dynamicbeans.JsonPlaceHolderApi
在这里连接到一个ConfigiruationProperties
类:https ://github.com/ciscoo/dynamicbeans/blob/master/src/main/java/io/mateo/dynamicbeans/FeignConfigurationProperties.java
然后我想注入ConfigiruationProperties
类与我在此处定义的工厂 bean 一起注入:https ://github.com/ciscoo/dynamicbeans/blob/master/src/main/java/io/mateo/dynamicbeans/FeignClientAutoConfiguration.java
所以现在我有以下内容:
@Component
public class FeignClientFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
private final FeignConfigurationProperties properties;
private final FeignClientFactory feignClientFactory;
public FeignClientFactoryPostProcessor(FeignConfigurationProperties properties, FeignClientFactory feignClientFactory) {
this.properties = properties;
this.feignClientFactory = feignClientFactory;
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
properties.getDownstreamServices().getRest().forEach((beanName, props) -> makeClient(beanName, props, registry));
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// no-op
}
private void makeClient(String beanName, FeignClientProperties props, BeanDefinitionRegistry registry) {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(props.getApiType());
beanDefinition.setInstanceSupplier(() -> feignClientFactory.create(props));
registry.registerBeanDefinition(beanName, beanDefinition);
}
}
它应该创建的单个 bean 是在此处注入服务类: https ://github.com/ciscoo/dynamicbeans/blob/master/src/main/java/io/mateo/dynamicbeans/JsonPlaceHolderService.java
我遇到的问题是:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.mateo.dynamicbeans.FeignClientFactoryPostProcessor]: No default constructor found; nested exception is java.lang.NoSuchMethodException: io.mateo.dynamicbeans.FeignClientFactoryPostProcessor.<init>()
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:83) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1262) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
... 17 common frames omitted
Caused by: java.lang.NoSuchMethodException: io.mateo.dynamicbeans.FeignClientFactoryPostProcessor.<init>()
at java.base/java.lang.Class.getConstructor0(Class.java:3350) ~[na:na]
at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2554) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:78) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
... 18 common frames omitted
但是当我删除final
从两个属性和定义的构造函数中删除关键字时,我得到一个NullPointerException
.
那么如何动态创建N个 bean以便它们可以及时用于我的任何@Service
类使用?
我知道https://spring.io/projects/spring-cloud-openfeign。我在这里重新创建了我的问题,以说明我在动态创建 SOAP 客户端的不同项目中遇到的相同问题。
更新:进行以下更改:https ://github.com/ciscoo/dynamicbeans/commit/4f16de9d03271025cd65d95932a3e854c0619c29 ,现在我可以完成我的用例了。
解决方案
正如您链接到的问题的答案所暗示的那样,您不能将依赖项注入到 bean 工厂后处理器中。您需要以编程方式绑定它,而不是注入您的配置属性类。在 Spring Boot 2.x 中,这是使用Binder
API实现的:
新的 Binder API 也可以
@ConfigurationProperties
在您自己的代码之外直接使用。例如,以下将绑定到一个List
对象PersonName
:List<PersonName> people = Binder.get(environment) .bind("my.property", Bindable.listOf(PersonName.class)) .orElseThrow(IllegalStateException::new);
配置源可以像这样在 YAML 中表示:
my: property: - first-name: Jane last-name: Doe - first-name: John last-name: Doe
推荐阅读
- async-await - 使用期货从套接字列表中选择
- facebook - 为一个 Facebook 应用程序使用多个不同的域
- php - 支持mysql的php动态复选框
- javascript - 在海报加载之前强制播放视频
- javascript - 如何在范围内获得总和?
- mysql - 在 VBA 宏中执行从 Excel 表中获取输入的 SQL 查询
- angular - 如何在前端使用 Angular 7 和在后端使用 Spring Boot 调试应用程序
- javascript - 在 Magento 2 中编辑前端的最佳方法是什么?
- python - 如何检查元素是否显示在下一页上?
- java - Kafka Streams:如何通过一对多关系丰富嵌套对象中的多个字段