なぜそれについて書くのですか?
これは私の最初の記事であり、フレームワークの内部でSpringRepositoryで得た実際の経験について説明しようと思います。このトピックに関する既製の記事は、ロシア語でも英語でもインターネット上で見つかりませんでした。githubにはソースリポジトリがわずかしかなく、Spring自体のソースコードもありませんでした。したがって、私は、なぜ書いてみませんか、突然、Spring用に独自のタイプのリポジトリを作成するというトピックが他の誰かに関連していると判断しました。
Infinispanのプログラミングについては詳しく説明しません。実装の詳細は、記事の最後に指定されているソースコードでいつでも確認できます。主な重点は、Spring BootRepositoryメカニズムと新しいタイプのリポジトリの組み合わせにあります。
すべてが始まった経緯
プロジェクトの1つに取り組んでいるときに、アーキテクトの1人は、さまざまなSpringモジュール(たとえば、JPARepository、KeyValueRepository、CassandraRepositoryなど)で行われるように、類推によって独自のタイプのリポジトリを作成できるという考えを持っていました。試行的な実装として、Infinispanを介したデータの操作を選択することにしました。
当然、アーキテクトは忙しい人なので、Java開発者がアイデアを実装するように割り当てられました。私に。
私がインターネットでこのトピックに取り組み始めたとき、Googleは、JPARepositoryをあらゆる種類で使用することの素晴らしさについて、簡単な例を挙げて、ほぼ1つの記事を頑固に発表しました。KeyValueRepositoryに関する情報はさらに少なかった。StackOverFlowには、同様のトピックに関する悲しい未回答の質問があります。何もすることはありません、私は春の情報源に行かなければなりませんでした。
インフィニスパン
Infinispanについて簡単に説明すると、これはキー値の形式の分散データストレージであり、これらすべてが常にメモリにキャッシュされます。Infinispanをオーバーロードすると、データはすべてゼロになります。
, - KeyValueRepository, , Spring. , Infinispan ( Hazelcast, ), , KeyValueRepository ConcurrentHashMap.
Spring - EnableMapRepositories.
@SpringBootApplication
@EnableMapRepositories("my.person.package.for.entities")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
EnableInfinispanRepositories.
, , map infinispan, , .
EnableInfinispanRepositories
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(InfinispanRepositoriesRegistrar.class)
public @interface EnableInfinispanRepositories {
String[] value() default {};
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
ComponentScan.Filter[] excludeFilters() default {};
ComponentScan.Filter[] includeFilters() default {};
String repositoryImplementationPostfix() default "Impl";
String namedQueriesLocation() default "";
QueryLookupStrategy.Key queryLookupStrategy() default
QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND;
Class<?> repositoryFactoryBeanClass() default
KeyValueRepositoryFactoryBean.class;
Class<?> repositoryBaseClass() default
DefaultRepositoryBaseClass.class;
String keyValueTemplateRef() default "infinispanKeyValueTemplate";
boolean considerNestedRepositories() default false;
}
EnableMapRepositories, , , .
@Import(MapRepositoriesRegistrar.class)
public @interface EnableMapRepositories {
}
MapRepositoriesRegistar.
public class MapRepositoriesRegistrar extends
RepositoryBeanDefinitionRegistrarSupport {
@Override
protected Class<? extends Annotation> getAnnotation() {
return EnableMapRepositories.class;
}
@Override
protected RepositoryConfigurationExtension getExtension() {
return new MapRepositoryConfigurationExtension();
}
}
. Registar , . , .
InfinispaRepositoriesRegistar.
@NoArgsConstructor
public class InfinispanRepositoriesRegistrar extends
RepositoryBeanDefinitionRegistrarSupport {
@Override
protected Class<? extends Annotation> getAnnotation() {
return EnableInfinispanRepositories.class;
}
@Override
protected RepositoryConfigurationExtension getExtension() {
return new InfinispanRepositoryConfigurationExtension();
}
}
, .
public class MapRepositoryConfigurationExtension extends
KeyValueRepositoryConfigurationExtension {
@Override
public String getModuleName() {
return "Map";
}
@Override
protected String getModulePrefix() {
return "map";
}
@Override
protected String getDefaultKeyValueTemplateRef() {
return "mapKeyValueTemplate";
}
@Override
protected AbstractBeanDefinition getDefaultKeyValueTemplateBeanDefinition(RepositoryConfigurationSource configurationSource) {
BeanDefinitionBuilder adapterBuilder = BeanDefinitionBuilder
.rootBeanDefinition(MapKeyValueAdapter.class);
adapterBuilder.addConstructorArgValue(
getMapTypeToUse(configurationSource));
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.rootBeanDefinition(KeyValueTemplate.class);
...
}
...
}
MapKeyValueAdapter , HashMap. KeyValueTemplate .
Infinispan, ConfigurationExtension, , // , Infinispan.
InfinispanRepositoriesConfigurationExtension
@NoArgsConstructor
public class InfinispanRepositoryConfigurationExtension
extends KeyValueRepositoryConfigurationExtension {
@Override
public String getModuleName() {
return "Infinispan";
}
@Override
protected String getModulePrefix() {
return "infinispan";
}
@Override
protected String getDefaultKeyValueTemplateRef() {
return "infinispanKeyValueTemplate";
}
@Override
protected Collection<Class<?>> getIdentifyingTypes() {
return Collections.singleton(InfinispanRepository.class);
}
@Override
protected AbstractBeanDefinition getDefaultKeyValueTemplateBeanDefinition(RepositoryConfigurationSource configurationSource) {
RootBeanDefinition infinispanKeyValueAdapterDefinition =
new RootBeanDefinition(InfinispanKeyValueAdapter.class);
RootBeanDefinition keyValueTemplateDefinition =
new RootBeanDefinition(KeyValueTemplate.class);
ConstructorArgumentValues constructorArgumentValuesForKeyValueTemplate = new ConstructorArgumentValues();
constructorArgumentValuesForKeyValueTemplate
.addGenericArgumentValue(infinispanKeyValueAdapterDefinition);
keyValueTemplateDefinition.setConstructorArgumentValues(
constructorArgumentValuesForKeyValueTemplate);
return keyValueTemplateDefinition;
}
}
ConfigurationExtension getIdentifyingTypes(), (. ).
@NoRepositoryBean
public interface InfinispanRepository <T, ID> extends
PagingAndSortingRepository<T, ID> {
}
, KeyValueTemplate, .
@Configuration
public class InfinispanConfiguration extends CachingConfigurerSupport {
@Autowired
private ApplicationContext applicationContext;
@Bean
public InfinispanKeyValueAdapter getInfinispanAdapter() {
return new InfinispanKeyValueAdapter(
applicationContext.getBean(CacheManager.class)
);
}
@Bean("infinispanKeyValueTemplate")
public KeyValueTemplate getInfinispanKeyValueTemplate() {
return new KeyValueTemplate(getInfinispanAdapter());
}
}
.
, , Spring- , , , .
概要
クラスを6つだけ作成したので、Infinispanをデータストアとして使用できる新しいタイプのリポジトリを入手しました。そして、この新しいタイプのリポジトリは、標準のSpringリポジトリと非常によく似ています。
完全なソースキットは私のgithubにあります。
Spring DataKeyValueソースはgithubでも見ることができます。
この実装について建設的なコメントがある場合は、コメントを書き込むか、元のプロジェクトでプルリクエストを行うことができます。