在Spring中改进自动配置

时间:2017-08-19 18:11:06

标签: java spring-boot retrofit2

我目前正在为Retrofit 2撰写Spring Boot自动配置。我要做的是编写某种接口构建器,它能够实例化一个带有一些注释的接口,用于自动装配,就像Spring Data使用存储库一样。由于我找不到任何关于如何做到这一点的资源(或者甚至可以用Spring完成),我想问你对此的看法。下面是我想要实例化的接口 我替换@Repository的是@Retrofit,其余的只是您为任何Retrofit存储库编写的“普通”代码。

我想要自动连接的界面:

@Retrofit
public interface Api {

    @GET("usernames")
    String[] getUsernames();
}

自动装配的示例:

@SpringBootApplication
public class TestApplication {

    @Autowired
    private Api api;

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }

    @Bean
    CommandLineRunner runner() {
        return args -> {
            System.out.println(api.getUsernames());
        };
    }
}

2 个答案:

答案 0 :(得分:1)

正如我所说,我找到了解决问题的方法。

首先,我们需要一个由Spring Boot加载的自动配置类 - 如所述here - 通过添加文件META-INF/spring.factories和下面显示的内容。此自动配置加载注册器,注册器本身通过组件提供程序搜索使用@Retrofit注释的类。最后,注册商为每个实例创建RetrofitFactoryBean的实例,这个实例可以在此工厂bean创建自己的Retrofit代理时找到。

自动配置

@Configuration
@Import(RetrofitRegistrar.class)
public class RetrofitAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public Retrofit retrofit() {
        return new Retrofit.Builder().build();
    }
}

<强> META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
spring.retrofit.RetrofitAutoConfiguration

导入的注册商

public class RetrofitRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {

    @Setter
    private BeanFactory beanFactory;

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
            BeanDefinitionRegistry registry) {
        List<String> basePackages = AutoConfigurationPackages.get(this.beanFactory);
        RetrofitComponentProvider provider = new RetrofitComponentProvider(registry);
        basePackages.stream()
                .map(provider::findCandidateComponents)
                .flatMap(Set::stream)
                .forEach(comp -> register(comp, registry));
    }

    private void register(BeanDefinition component, BeanDefinitionRegistry registry) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.
                rootBeanDefinition(RetrofitFactoryBean.class);
        builder.addConstructorArgValue(component.getBeanClassName());
        registry.registerBeanDefinition(
                component.getBeanClassName().toLowerCase(), builder.getBeanDefinition());
    }
}

组件提供商

class RetrofitComponentProvider extends ClassPathScanningCandidateComponentProvider {

    @Getter
    private BeanDefinitionRegistry registry;

    public RetrofitComponentProvider(BeanDefinitionRegistry registry) {
        super(false);

        Assert.notNull(registry, "BeanDefinitionRegistry must not be null!");
        this.registry = registry;

        addIncludeFilter(new AnnotationTypeFilter(Retrofit.class, true, true));
    }

    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return true;
    }
}

工厂bean

@Component
@RequiredArgsConstructor
public class RetrofitFactoryBean extends AbstractFactoryBean<Object> {

    @Getter
    private final Class<?> objectType;
    private final retrofit2.Retrofit retrofit;

    @Override
    protected Object createInstance() throws Exception {
        return retrofit.create(objectType);
    }
}

@Getter提供@Setter@RequiredArgsConstructorcurses注释{/ 3}}

答案 1 :(得分:0)

让我首先要求你通过创建一个新的Spring注释来避免重新发明轮子(你的这里是$(document).ready(function(){ var tagsToSend = "tag1%tag2%tag3%tag4%tag5%tag6%tag7%tag8%tag9%tag10%tag11%tag12%tag13"; $.ajax({ url: "test.php", method: "POST", data: { tags: tagsToSend }, success: function(result){ alert(result) } }); }) 。但是,使用spring进行改造是绝对可以的,没有什么可以阻止它。你可以简单地尝试使用现有的Spring注释,@Retrofit可以在this question中看到 您可以自动装配您的界面而不会遇到任何问题 希望这会有所帮助。