2017-08-19 7 views
1

私は現在Retrofit 2のためにSpring Bootの自動設定を書いています。私がやろうとしているのは、Spring Dataのようにいくつかの注釈が付いたインターフェイスをインスタンス化できるインターフェイスビルダを書くことです。これをどうやって行うのかについてのリソースが見つからないので(またはSpringでもできていても)、私はあなたの考えを尋ねたいと思います。以下は、私がインスタンス化したいインターフェイスです。
@Repositoryの代わりに@Retrofitがあります。残りは、Retrofitリポジトリ用に書かれた「通常の」コードです。春の自動設定の変更

私はautowireしたいインターフェイスの種類:

@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()); 
     }; 
    } 
} 
+0

によって提供されているが、あなたはそれをautowireしてみましたか?もしあれば、コードとエラーがあればそれを置いてください。 – MrMisery

+0

例を追加しましたが、明らかに動作しません。特定のインタフェースのインスタンスが見つからないためです。エラーは 'com.example.TestApplicationのフィールドapiは 'com.example型のBeanを必要としました。Api 'を見つけることができませんでした。 –

答えて

1

私が言ったように、私の問題の解決策が見つかりました。 hereを述べたように - - 以下のようになり、コンテンツのファイルMETA-INF/spring.factoriesを追加することにより、

まず我々はSpring Bootによってロードされた自動構成クラスが必要です。この自動構成では、レジストラがロードされ、コンポーネントプロバイダを介して@Retrofitという注釈付きクラスを検索します。最後に、レジストラは、このファクトリBeanがRetrofitプロキシ自体を作成している間に見つかる可能性があるインスタンスごとにRetrofitFactoryBeanというインスタンスを作成します。

自動設定

@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; 
    } 
} 

工場豆

@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@RequiredArgsConstructor注釈がProjectLombok

0

私は(新しい春の注釈を作成することにより、車輪の再発明を避けるために、まずお聞きしてみましょうここでは@Retrofitですが、春にレトロフィットを使用することは絶対に許されません。それを防ぐことは何もありません。this questionのように、@Componentのような既存の春の注釈を使用してみてください。あなたは問題に直面することなくインターフェイスをオートワイヤリングできます。
これが役に立ちます。

+0

リンクされた質問では、インターフェイスの実装がユーザによって与えられます。私はユーザーがそれをする必要はありませんが、むしろ "フレームワーク"がRetrofitのインスタンス化メカニズムを使用してインターフェイスをインスタンス化する作業をしたいと思っています。だからこそ、私はSpring Dataに言及しています。これはまた、インターフェイスをすべてインスタンス化します。 –

関連する問題