feat: 尽可能解耦reflections

This commit is contained in:
wangyu 2023-09-18 22:12:00 +08:00
parent ec0c1afef7
commit 119e9b67e9
6 changed files with 124 additions and 19 deletions

View File

@ -59,10 +59,6 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,109 @@
package com.flyfish.framework.utils;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.lang.NonNull;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.*;
/**
* 内部的包扫描器提供特定注解扫描
*
* @author wangyu
*/
public class ClassPathResourceScanner extends ClassPathScanningCandidateComponentProvider {
private final TypeFilter filter;
/**
* 扫描某个特定注解
*
* @param annoType 注解类型
* @return 结果
*/
public static ClassPathResourceScanner forAnnotation(Class<? extends Annotation> annoType) {
return new ClassPathResourceScanner(new AnnotationTypeFilter(annoType));
}
/**
* 扫描子类
*
* @param superType 父类型
* @return 结果
*/
public static ClassPathResourceScanner forSuperType(Class<?> superType) {
return new ClassPathResourceScanner(new AssignableTypeFilter(superType));
}
private ClassPathResourceScanner(TypeFilter filter) {
super(false);
this.filter = filter;
resetFilters(false);
addIncludeFilter(filter);
}
@Override
protected boolean isCandidateComponent(@NonNull MetadataReader metadataReader) throws IOException {
return filter.match(metadataReader, getMetadataReaderFactory());
}
@Override
protected boolean isCandidateComponent(@NonNull AnnotatedBeanDefinition beanDefinition) {
return true;
}
private Class<?> resolveType(BeanDefinition bf, ClassLoader cl) {
if (null != bf.getBeanClassName()) {
try {
return ClassUtils.forName(bf.getBeanClassName(), cl);
} catch (ClassNotFoundException e) {
return null;
}
}
return null;
}
/**
* 扫描类
*
* @param packageNames 包名
* @return 结果
*/
public Set<Class<?>> scan(Collection<String> packageNames) {
// 获取扫描器的ClassLoader保证同源
ClassLoader cl = this.getClass().getClassLoader();
Set<Class<?>> scanned = new HashSet<>();
for (String packageName : packageNames) {
Set<BeanDefinition> bfs = findCandidateComponents(packageName);
// 不存在不要浪费性能
if (CollectionUtils.isEmpty(bfs)) continue;
// 代理并生成子类并注册到ioc容器
for (BeanDefinition bf : bfs) {
Class<?> resolved = resolveType(bf, cl);
if (null != resolved) {
scanned.add(resolved);
}
}
}
return scanned;
}
/**
* 扫描类
*
* @param packageNames 包名
* @return 结果
*/
public Set<Class<?>> scan(String... packageNames) {
return scan(Arrays.asList(packageNames));
}
}

View File

@ -2,9 +2,9 @@ package com.flyfish.framework.config;
import com.flyfish.framework.bean.EnumValue;
import com.flyfish.framework.enums.NamedEnum;
import com.flyfish.framework.utils.ClassPathResourceScanner;
import com.flyfish.framework.utils.StringFormats;
import org.apache.commons.lang3.ClassUtils;
import org.reflections.Reflections;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
@ -13,6 +13,7 @@ import java.util.stream.Collectors;
/**
* 枚举相关专门处理枚举
*
* @author wangyu
*/
public class EnumConfig implements InitializingBean, ImportBeanDefinitionRegistrar {
@ -23,14 +24,13 @@ public class EnumConfig implements InitializingBean, ImportBeanDefinitionRegistr
private final Map<String, List<EnumValue>> values = new HashMap<>();
public EnumConfig() {
Reflections reflections = new Reflections("com.flyfish.project");
// 得到Resource注解的类
Set<Class<? extends NamedEnum>> classSet = reflections.getSubTypesOf(NamedEnum.class);
// 得到枚举类
Set<Class<?>> classSet = ClassPathResourceScanner.forSuperType(NamedEnum.class).scan("com.flyfish.project");
// 注入
classSet.stream().filter(clazz -> ClassUtils.isAssignable(clazz, Enum.class)).forEach(clazz -> {
String name = StringFormats.camel2Line(clazz.getSimpleName());
List<EnumValue> values = Arrays.stream(clazz.getEnumConstants()).reduce(new ArrayList<>(), (result, item) -> {
result.add(new EnumValue(((Enum<?>) item).name(), item.getName()));
result.add(new EnumValue(((Enum<?>) item).name(), ((NamedEnum) item).getName()));
return result;
}, (a, b) -> a);
this.mapper.put(name, values.stream().collect(Collectors.toMap(EnumValue::getValue, EnumValue::getText)));

View File

@ -24,5 +24,9 @@
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -12,11 +12,11 @@ import com.flyfish.framework.domain.base.Vo;
import com.flyfish.framework.repository.DefaultReactiveRepository;
import com.flyfish.framework.repository.DefaultRepository;
import com.flyfish.framework.utils.Assert;
import com.flyfish.framework.utils.ClassPathResourceScanner;
import com.flyfish.framework.utils.StringFormats;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.reflections.Reflections;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@ -76,17 +76,15 @@ public class RestBeanAutoConfigure implements ImportBeanDefinitionRegistrar, Res
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry, BeanNameGenerator beanNameGenerator) {
log.info("开始注册rest bean...");
// 获取元数据
// 获取包路径元数据
Set<String> basePackages = getBasePackages(metadata);
// 扫描包路径检测RestBean注解的bean
Reflections reflections = new Reflections(basePackages);
// repo注册器
RepositoryRegistrar repositoryRegistrar = RepositoryRegistrar.newInstance(metadata)
.init(metadata, resourceLoader, environment, registry, beanNameGenerator);
// 寻找基本包路径
String basePackage = basePackages.stream().findFirst().orElse("com.flyfish.project");
// 获取被注解的类开始编译
Set<Class<?>> classes = reflections.getTypesAnnotatedWith(RestBean.class);
Set<Class<?>> classes = ClassPathResourceScanner.forAnnotation(RestBean.class).scan(basePackages);
// 并发编译快速接入准备注册的repo
Map<RestBeanCandidate, List<String>> compiledClasses = compile(basePackage, classes);
// 从repo开始注册bean

View File

@ -3,9 +3,9 @@ package com.flyfish.framework.controller;
import com.flyfish.framework.bean.EnumValue;
import com.flyfish.framework.bean.Result;
import com.flyfish.framework.enums.NamedEnum;
import com.flyfish.framework.utils.ClassPathResourceScanner;
import com.flyfish.framework.utils.StringFormats;
import org.apache.commons.lang3.ClassUtils;
import org.reflections.Reflections;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@ -30,14 +30,12 @@ public class EnumController {
private final Map<String, List<EnumValue>> values = new HashMap<>();
public EnumController() {
Reflections reflections = new Reflections("com.flyfish.project", "com.flyfish.framework");
// 得到Resource注解的类
Set<Class<? extends NamedEnum>> classSet = reflections.getSubTypesOf(NamedEnum.class);
Set<Class<?>> classSet = ClassPathResourceScanner.forSuperType(NamedEnum.class).scan("com.flyfish.project", "com.flyfish.framework");
// 注入
classSet.stream().filter(clazz -> ClassUtils.isAssignable(clazz, Enum.class)).forEach(clazz -> {
String name = StringFormats.camel2Line(ClassUtils.getShortClassName(clazz));
List<EnumValue> values = Arrays.stream(clazz.getEnumConstants()).reduce(new ArrayList<>(), (result, item) -> {
result.add(new EnumValue(((Enum<?>) item).name(), item.getName()));
result.add(new EnumValue(((Enum<?>) item).name(), ((NamedEnum) item).getName()));
return result;
}, (a, b) -> a);
this.mapper.put(name, values.stream().collect(Collectors.toMap(EnumValue::getValue, EnumValue::getText)));