feat:优化仓库注册,动态导入

This commit is contained in:
wangyu 2022-10-03 22:21:14 +08:00
parent eb23176b78
commit 040452e066
7 changed files with 168 additions and 71 deletions

View File

@ -0,0 +1,15 @@
package com.flyfish.framework.utils;
/**
* 构建器表示
*/
@FunctionalInterface
public interface Builder<T> {
/**
* 构建对象
*
* @return 构建结果
*/
T build();
}

View File

@ -1,11 +1,5 @@
package com.flyfish.framework.beans.repository; package com.flyfish.framework.beans.repository;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition;
@ -22,6 +16,10 @@ import org.springframework.data.repository.core.support.RepositoryFragmentsFacto
import org.springframework.data.util.Optionals; import org.springframework.data.util.Optionals;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import java.util.Collections;
import java.util.Optional;
import java.util.stream.Stream;
/** /**
* Builder to create {@link BeanDefinitionBuilder} instance to eventually create Spring Data repository instances. * Builder to create {@link BeanDefinitionBuilder} instance to eventually create Spring Data repository instances.
* *
@ -30,7 +28,7 @@ import org.springframework.util.Assert;
* @author Peter Rietzler * @author Peter Rietzler
* @author Mark Paluch * @author Mark Paluch
*/ */
public class CustomRepositoryBuilder { class CustomRepositoryBuilder {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomRepositoryBuilder.class); private static final Logger LOGGER = LoggerFactory.getLogger(CustomRepositoryBuilder.class);
@ -46,15 +44,13 @@ public class CustomRepositoryBuilder {
* Creates a new {@link CustomRepositoryBuilder} from the given {@link BeanDefinitionRegistry}, * Creates a new {@link CustomRepositoryBuilder} from the given {@link BeanDefinitionRegistry},
* {@link RepositoryConfigurationExtension} and {@link ResourceLoader}. * {@link RepositoryConfigurationExtension} and {@link ResourceLoader}.
* *
* @param registry must not be {@literal null}. * @param registry must not be {@literal null}.
* @param extension must not be {@literal null}.
* @param resourceLoader must not be {@literal null}. * @param resourceLoader must not be {@literal null}.
* @param environment must not be {@literal null}. * @param environment must not be {@literal null}.
*/ */
public CustomRepositoryBuilder(BeanDefinitionRegistry registry, RepositoryConfigurationExtension extension, CustomRepositoryBuilder(BeanDefinitionRegistry registry, RepositoryConfigurationExtension extension, RepositoryConfigurationSource configurationSource,
RepositoryConfigurationSource configurationSource, ResourceLoader resourceLoader, Environment environment) { ResourceLoader resourceLoader, Environment environment) {
Assert.notNull(extension, "RepositoryConfigurationExtension must not be null!");
Assert.notNull(resourceLoader, "ResourceLoader must not be null!"); Assert.notNull(resourceLoader, "ResourceLoader must not be null!");
Assert.notNull(environment, "Environment must not be null!"); Assert.notNull(environment, "Environment must not be null!");

View File

@ -0,0 +1,44 @@
package com.flyfish.framework.beans.repository;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
/**
* 仓库注册器
*
* @author wangyu
*/
public interface RepositoryRegistrar {
/**
* 初始化注册器不初始化无法使用
*
* @param metadata 元数据
* @param resourceLoader 资源加载器
* @param environment 环境变量
* @param registry bean注册器
* @param generator 生成器
* @return 结果
*/
RepositoryRegistrar init(AnnotationMetadata metadata, ResourceLoader resourceLoader, Environment environment,
BeanDefinitionRegistry registry, BeanNameGenerator generator);
/**
* 根据class直接注册bean
*
* @param clazz 编译后的class
*/
void register(Class<?> clazz);
/**
* 创建新的注册器
*
* @return 注册器
*/
static RepositoryRegistrar newInstance(AnnotationMetadata metadata) {
return new RepositoryRegistrarComposite(metadata);
}
}

View File

@ -0,0 +1,51 @@
package com.flyfish.framework.beans.repository;
import com.flyfish.framework.repository.DefaultReactiveRepository;
import com.flyfish.framework.repository.DefaultRepository;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories;
import org.springframework.data.mongodb.repository.config.MongoRepositoryConfigurationExtension;
import org.springframework.data.mongodb.repository.config.ReactiveMongoRepositoryConfigurationExtension;
import java.util.ArrayList;
import java.util.List;
/**
* 注册器组合对象
*
* @author wangyu
*/
class RepositoryRegistrarComposite implements RepositoryRegistrar {
private final List<RepositoryRegistrar> registrars;
RepositoryRegistrarComposite(AnnotationMetadata metadata) {
List<RepositoryRegistrar> list = new ArrayList<>();
if (metadata.hasMetaAnnotation(EnableMongoRepositories.class.getName())) {
list.add(new SimpleRepositoryRegistrar(EnableMongoRepositories.class, new MongoRepositoryConfigurationExtension(),
DefaultRepository.class));
}
if (metadata.hasMetaAnnotation(EnableReactiveMongoRepositories.class.getName())) {
list.add(new SimpleRepositoryRegistrar(EnableReactiveMongoRepositories.class, new ReactiveMongoRepositoryConfigurationExtension(),
DefaultReactiveRepository.class));
}
this.registrars = list;
}
@Override
public RepositoryRegistrar init(AnnotationMetadata metadata, ResourceLoader resourceLoader, Environment environment,
BeanDefinitionRegistry registry, BeanNameGenerator generator) {
registrars.forEach(registrar -> registrar.init(metadata, resourceLoader, environment, registry, generator));
return this;
}
@Override
public void register(Class<?> clazz) {
registrars.forEach(registrar -> registrar.register(clazz));
}
}

View File

@ -1,7 +1,5 @@
package com.flyfish.framework.beans.repository; package com.flyfish.framework.beans.repository;
import com.flyfish.framework.repository.DefaultReactiveRepository;
import com.flyfish.framework.repository.DefaultRepository;
import org.apache.commons.lang3.ClassUtils; import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.FactoryBean;
@ -13,54 +11,65 @@ import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories;
import org.springframework.data.mongodb.repository.config.MongoRepositoryConfigurationExtension;
import org.springframework.data.mongodb.repository.config.ReactiveMongoRepositoryConfigurationExtension;
import org.springframework.data.repository.config.*; import org.springframework.data.repository.config.*;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.List;
/** /**
* 自定义的仓库注册器 * 简单的仓库注册器
* *
* @author wangyu * @author wangyu
* 封装大部分逻辑
*/ */
public class CustomRepositoryRegistrar { class SimpleRepositoryRegistrar implements RepositoryRegistrar {
// repo生成的extension private final RepositoryConfigurationExtension extension;
private final RepositoryConfigurationExtension extension = new MongoRepositoryConfigurationExtension(); private RepositoryConfigurationSource configurationSource;
private final RepositoryConfigurationSource configurationSource; private CustomRepositoryBuilder builder;
private final CustomRepositoryBuilder builder; // 支持的注解类型
// 异步的extension private final Class<? extends Annotation> annotationType;
private final RepositoryConfigurationExtension reactiveExtension = new ReactiveMongoRepositoryConfigurationExtension(); // 支持的仓库类型
private final RepositoryConfigurationSource reactiveConfigurationSource; private final List<Class<?>> supportedTypes;
private final CustomRepositoryBuilder reactiveBuilder;
public CustomRepositoryRegistrar(AnnotationMetadata metadata, ResourceLoader resourceLoader, Environment environment, SimpleRepositoryRegistrar(Class<? extends Annotation> annotationType, RepositoryConfigurationExtension extension,
BeanDefinitionRegistry registry, BeanNameGenerator generator) { Class<?>... supportedTypes) {
// repo生成的构建器 this.annotationType = annotationType;
this.configurationSource = new AnnotationRepositoryConfigurationSource(metadata, this.extension = extension;
EnableMongoRepositories.class, resourceLoader, environment, registry, generator); this.supportedTypes = Arrays.asList(supportedTypes);
// 异步的repo生成的构建器
this.reactiveConfigurationSource = new AnnotationRepositoryConfigurationSource(metadata,
EnableReactiveMongoRepositories.class, resourceLoader, environment, registry, generator);
// 构建器
this.builder = new CustomRepositoryBuilder(registry, extension,
configurationSource, resourceLoader, environment);
// 异步的构造器
this.reactiveBuilder = new CustomRepositoryBuilder(registry, reactiveExtension, reactiveConfigurationSource,
resourceLoader, environment);
} }
/** /**
* 根据class直接注册bean * 初始化注册器不初始化无法使用
* *
* @param metadata 元数据
* @param resourceLoader 资源加载器
* @param environment 环境变量
* @param registry bean注册器
* @param generator 生成器
* @return 结果
*/
@Override
public RepositoryRegistrar init(
AnnotationMetadata metadata, ResourceLoader resourceLoader, Environment environment,
BeanDefinitionRegistry registry, BeanNameGenerator generator) {
// repo生成的构建器
this.configurationSource = new AnnotationRepositoryConfigurationSource(metadata,
annotationType, resourceLoader, environment, registry, generator);
// 构建器
this.builder = new CustomRepositoryBuilder(registry, extension,
configurationSource, resourceLoader, environment);
return this;
}
/**
* @param clazz 编译后的class * @param clazz 编译后的class
*/ */
@Override
public void register(Class<?> clazz) { public void register(Class<?> clazz) {
if (ClassUtils.isAssignable(clazz, DefaultRepository.class)) { if (supportedTypes.stream().anyMatch(type -> ClassUtils.isAssignable(clazz, type))) {
register(clazz, configurationSource, extension, builder); register(clazz, configurationSource, builder);
} else if (ClassUtils.isAssignable(clazz, DefaultReactiveRepository.class)) {
register(clazz, reactiveConfigurationSource, reactiveExtension, reactiveBuilder);
} }
} }
@ -69,10 +78,10 @@ public class CustomRepositoryRegistrar {
* *
* @param clazz 类型 * @param clazz 类型
* @param configurationSource 配置源 * @param configurationSource 配置源
* @param extension 扩展
* @param builder 构建器 * @param builder 构建器
*/ */
private void register(Class<?> clazz, RepositoryConfigurationSource configurationSource, RepositoryConfigurationExtension extension, CustomRepositoryBuilder builder) { private void register(Class<?> clazz, RepositoryConfigurationSource configurationSource,
CustomRepositoryBuilder builder) {
//生成BeanDefinition并注册到容器中 //生成BeanDefinition并注册到容器中
BeanDefinition origin = BeanDefinitionBuilder.genericBeanDefinition(clazz).getRawBeanDefinition(); BeanDefinition origin = BeanDefinitionBuilder.genericBeanDefinition(clazz).getRawBeanDefinition();
//设置当前bean定义对象是单例的 //设置当前bean定义对象是单例的
@ -89,9 +98,4 @@ public class CustomRepositoryRegistrar {
beanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, configuration.getRepositoryInterface()); beanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, configuration.getRepositoryInterface());
builder.getRegistry().registerBeanDefinition(beanName, beanDefinition); builder.getRegistry().registerBeanDefinition(beanName, beanDefinition);
} }
public RepositoryConfigurationExtension getExtension() {
return extension;
}
} }

View File

@ -3,7 +3,7 @@ package com.flyfish.framework.config;
import com.flyfish.framework.beans.annotations.EnableRestBeanDetect; import com.flyfish.framework.beans.annotations.EnableRestBeanDetect;
import com.flyfish.framework.beans.enums.RestBeanCandidate; import com.flyfish.framework.beans.enums.RestBeanCandidate;
import com.flyfish.framework.beans.meta.RestBean; import com.flyfish.framework.beans.meta.RestBean;
import com.flyfish.framework.beans.repository.CustomRepositoryRegistrar; import com.flyfish.framework.beans.repository.RepositoryRegistrar;
import com.flyfish.framework.beans.resolver.DynamicRestBeanResolver; import com.flyfish.framework.beans.resolver.DynamicRestBeanResolver;
import com.flyfish.framework.compiler.DynamicJavaCompiler; import com.flyfish.framework.compiler.DynamicJavaCompiler;
import com.flyfish.framework.compiler.support.JavaSource; import com.flyfish.framework.compiler.support.JavaSource;
@ -81,8 +81,8 @@ public class RestBeanAutoConfigure implements ImportBeanDefinitionRegistrar, Res
// 扫描包路径检测RestBean注解的bean // 扫描包路径检测RestBean注解的bean
Reflections reflections = new Reflections(basePackages); Reflections reflections = new Reflections(basePackages);
// repo注册器 // repo注册器
CustomRepositoryRegistrar repositoryRegistrar = new CustomRepositoryRegistrar(metadata, resourceLoader, RepositoryRegistrar repositoryRegistrar = RepositoryRegistrar.newInstance(metadata)
environment, registry, beanNameGenerator); .init(metadata, resourceLoader, environment, registry, beanNameGenerator);
// 准备注册的repo // 准备注册的repo
Map<RestBeanCandidate, List<Class<?>>> loadedClasses = new ConcurrentHashMap<>(); Map<RestBeanCandidate, List<Class<?>>> loadedClasses = new ConcurrentHashMap<>();
// 获取被注解的类开始编译 // 获取被注解的类开始编译

View File

@ -1,6 +1,5 @@
package com.flyfish.framework.configuration.boot; package com.flyfish.framework.configuration.boot;
import com.flyfish.framework.annotations.EnableMongoRepo;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.core.annotation.AliasFor; import org.springframework.core.annotation.AliasFor;
@ -18,23 +17,11 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
@Inherited @Inherited
@EnableMongoRepo
@SpringBootApplication @SpringBootApplication
@EnableAsync(proxyTargetClass = true) @EnableAsync(proxyTargetClass = true)
@EnableAspectJAutoProxy @EnableAspectJAutoProxy
public @interface FlyfishApplication { public @interface FlyfishApplication {
/**
* repo扫描的基础包
*
* @return 结果
*/
@AliasFor(
annotation = EnableMongoRepo.class,
attribute = "basePackages"
)
String[] repositoryBasePackages() default {};
/** /**
* 扫描组件的路径 * 扫描组件的路径
* *