Java 动态注册的第三方Bean上类似Spring的后处理器钩子

Java 动态注册的第三方Bean上类似Spring的后处理器钩子,java,spring,grpc,spring-bean,grpc-java,Java,Spring,Grpc,Spring Bean,Grpc Java,我在动态注册的第三方bean上使用什么Spring框架钩子 我有一个用于动态扫描类路径并实例化多个第三方bean(gRPCAbstractStub实例)的类路径。我需要在存根上注册,这样增强的AbstractStub就可以进行应用程序处理了。我使用动态创建的*Stub@Bean来消除所有@Bean样板文件,并确保一致的通道配置 约束条件 AbstractStub实现是gRPC生成的类。我的类扩展了AbstractStub 首选的静态工厂方法是:;这是在手动编译@Bean声明时使用的 每个存根都

我在动态注册的第三方bean上使用什么Spring框架钩子

我有一个用于动态扫描类路径并实例化多个第三方bean(gRPC
AbstractStub
实例)的类路径。我需要在存根上注册,这样增强的
AbstractStub
就可以进行应用程序处理了。我使用动态创建的
*Stub
@Bean
来消除所有
@Bean
样板文件,并确保一致的通道配置

约束条件
  • AbstractStub
    实现是gRPC生成的类。我的类扩展了
    AbstractStub
  • 首选的静态工厂方法是:;这是在手动编译
    @Bean
    声明时使用的
  • 每个存根都需要一个
    通道作为依赖项。有多个
    频道
    @bean
尝试 我尝试了三种方法:

方法1:
BeanDefinitionBuilder
+
供应商
功能 不允许注入
通道
依赖项

void registerBeanDefintion(final Class<S> clazz, final BeanDefinitionRegistry registry) {
    Supplier<S> stubSupplier = () -> {
        clazz.getConstructor({Channel.class});
        return BeanUtils.instantiateClass(constructor, null); // fails here; no Channel
    }
    BeanDefinitionBuilder builder =
        BeanDefinitionBuilder.genericBeanDefinition(clazz, stubSupplier);
    builder.addDependsOn(MANAGED_CHANNEL_BEAN_NAME);
    builder.addConstructorArgReference(MANAGED_CHANNEL_BEAN_NAME);
    registry.registerBeanDefinition(clazz.getName(), builder.getBeanDefinition());
方法3:
后处理BeanFactory()
postprocesseBeanFactory
不会对实例化的bean进行操作,因此依赖关系不会预先解析

public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    Iterator<String> iterator = configurableListableBeanFactory.getBeanNamesIterator();
    while (iterator.hasNext()) {
        String beanName = iterator.next();
        if (beanName.endsWith("Stub")) {
            AbstractStub stub = (AbstractStub) configurableListableBeanFactory.getBean(beanName); //fails
            stub.withInterceptors(newClientInterceptor()); // never gets executed
        }
    }
}
public void后处理BeanFactory(ConfigurableListableBeanFactoryConfigurableListableBeanFactory)抛出BeanException{
迭代器迭代器=configurableListableBeanFactory.GetBeanName迭代器();
while(iterator.hasNext()){
String beanName=iterator.next();
if(beanName.endsWith(“存根”)){
AbstractStub=(AbstractStub)configurableListableBeanFactory.getBean(beanName);//失败
stub.withInterceptors(newClientInterceptor());//永远不会执行
}
}
}

由于我有一些单独的模块,我把它复杂化了一点:解决方案是使用一个简单的
BeanPostProcessor
并调用
withInterceptors()
仅用于
AbstractStub
实例:

    @Override
    public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
        if (bean instanceof AbstractStub) {
            AbstractStub stub = (AbstractStub) bean;
            log.debug("modify bean '{}': add timeout client interceptor", beanName);
            ClientInterceptor timeoutClientInterceptor = this.newTimeoutClientInterceptor(stub);
            AbstractStub result = stub.withInterceptors(timeoutClientInterceptor);
            return result;
        }
        return bean;
    }

    ClientInterceptor newTimeoutClientInterceptor(final AbstractStub stub) {
        final Deadline deadline = this.getDeadlineTimeout(stub);
        return new ClientInterceptor() {
            @Override
            public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
                final ClientCall<ReqT, RespT> clientCall = next.newCall(method, callOptions.withDeadline(deadline));
                return new ClientInterceptors.CheckedForwardingClientCall<ReqT, RespT>(clientCall) {
                    @Override
                    protected void checkedStart(Listener<RespT> listener, Metadata metadata) {
                        log.debug("execute call with deadline {}", deadline);
                        delegate().start(listener, metadata);
                    }
                };
            }
        };
    }

@覆盖
公共对象后处理AfterInitialization(最终对象bean,最终字符串beanName)抛出BeanException{
if(抽象存根的bean实例){
AbstractStub=(AbstractStub)bean;
debug(“修改bean“{}”:添加超时客户端拦截器”,beanName);
ClientInterceptor timeoutClientInterceptor=此.newTimeoutClientInterceptor(存根);
AbstractStub result=stub.withInterceptors(timeoutClientInterceptor);
返回结果;
}
返回豆;
}
ClientInterceptor newTimeoutClientInterceptor(最终摘要存根){
最终截止日期=此.getDeadlineTimeout(存根);
返回新的ClientInterceptor(){
@凌驾
public ClientCall interceptCall(MethodDescriptor方法、CallOptions CallOptions、Channel next){
final ClientCall ClientCall=next.newCall(方法,callOptions.withDeadline(deadline));
返回新的ClientInterceptors.CheckedForwardingClientCall(clientCall){
@凌驾
受保护的void checkedStart(侦听器侦听器、元数据){
debug(“使用截止日期{}执行调用”,截止日期);
委托().start(侦听器、元数据);
}
};
}
};
}

在if块中,您有BeanDefinition BeanDefinition=并且它没有分配给任何对象?那是一辆汽车吗pasto@zee是的,复制意大利面。更新,thx
    @Override
    public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
        if (bean instanceof AbstractStub) {
            AbstractStub stub = (AbstractStub) bean;
            log.debug("modify bean '{}': add timeout client interceptor", beanName);
            ClientInterceptor timeoutClientInterceptor = this.newTimeoutClientInterceptor(stub);
            AbstractStub result = stub.withInterceptors(timeoutClientInterceptor);
            return result;
        }
        return bean;
    }

    ClientInterceptor newTimeoutClientInterceptor(final AbstractStub stub) {
        final Deadline deadline = this.getDeadlineTimeout(stub);
        return new ClientInterceptor() {
            @Override
            public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
                final ClientCall<ReqT, RespT> clientCall = next.newCall(method, callOptions.withDeadline(deadline));
                return new ClientInterceptors.CheckedForwardingClientCall<ReqT, RespT>(clientCall) {
                    @Override
                    protected void checkedStart(Listener<RespT> listener, Metadata metadata) {
                        log.debug("execute call with deadline {}", deadline);
                        delegate().start(listener, metadata);
                    }
                };
            }
        };
    }