【问题标题】:Create Bean for interface为接口创建 Bean
【发布时间】:2021-01-06 11:28:03
【问题描述】:

我正在尝试创建类似@Repository 的系统。

我有很多接口,例如:

@Client(uri = "http://example.com", username = "httpBasicUsername", password = "httpBasicPassword")
public interface RequestRepository {

     @Request(method = Method.POST, uri = "/mono")
     Mono<Response> ex1(Object body);

     @Request(method = Method.POST, uri = "/flux")
     Flux<Response> ex2(Object body);
}

现在,我正在使用这个函数创建 bean:

@Bean
public RequestRepository requestRepository(WebClient.Builder builder) {
    return (RequestRepository) Proxy.newProxyInstance(
            RequestRepository.class.getClassLoader(),
            new Class[]{RequestRepository.class},
            new MyDynamicInvocationHandler(builder)
    );
}

但是我有很多这样的接口。对于每个新接口,我都需要创建另一个 bean 函数。但我不想那样做。

如果有@Client注解,有没有办法说spring(spring boot)然后像这样创建bean等?

【问题讨论】:

  • BeanFactoryPostProcessor 接口可用于根据某些条件动态创建 bean。你可以在你的情况下使用它。为方便起见,我建议将所有类放在同一个包中。
  • 首先谢谢你。我必须创建自定义接口扫描仪并在其中注册我的代理。我是新的所有这些 bean 和代理的东西,所以再次感谢。

标签: java spring spring-boot


【解决方案1】:

我已经解决了创建自定义界面扫描器的问题。

更多详情:https://stackoverflow.com/a/43651431/6841566

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import({InterfaceScanner.class})
public @interface InterfaceScan {
    String[] value() default {};
}

public class InterfaceScanner implements ImportBeanDefinitionRegistrar, EnvironmentAware {
    private Environment environment;

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(InterfaceScan.class.getCanonicalName());
        if (annotationAttributes != null) {
            String[] basePackages = (String[]) annotationAttributes.get("value");
            if (basePackages.length == 0)
                basePackages = new String[]{((StandardAnnotationMetadata) metadata)
                        .getIntrospectedClass().getPackage().getName()};

            ClassPathScanningCandidateComponentProvider provider =
                    new ClassPathScanningCandidateComponentProvider(false, environment) {
                        @Override
                        protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
                            AnnotationMetadata meta = beanDefinition.getMetadata();
                            return meta.isIndependent() && meta.isInterface();
                        }
                    };
            provider.addIncludeFilter(new AnnotationTypeFilter(Client.class));
            for (String basePackage : basePackages)
                for (BeanDefinition beanDefinition : provider.findCandidateComponents(basePackage))
                    registry.registerBeanDefinition(
                            generateName(beanDefinition.getBeanClassName()),
                            getProxyBeanDefinition(beanDefinition.getBeanClassName()));
        }
    }
}

@InterfaceScan
@SpringBootApplication
public class ExampleApplication {
    ...
}

【讨论】:

    猜你喜欢
    • 2019-09-08
    • 2020-10-05
    • 2016-07-21
    • 1970-01-01
    • 2019-08-03
    • 1970-01-01
    • 2017-04-17
    • 2020-05-14
    • 1970-01-01
    相关资源
    最近更新 更多