ClassScanner
@Slf4j
public class ClassScanner implements ResourceLoaderAware {
private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);
private final List<TypeFilter> includeFilters = new LinkedList<>();
private final List<TypeFilter> excludeFilters = new LinkedList<>();
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
}
public void addIncludeFilter(TypeFilter includeFilter) {
this.includeFilters.add(includeFilter);
}
public void addExcludeFilter(TypeFilter excludeFilter) {
this.excludeFilters.add(0, excludeFilter);
}
public void resetFilters(boolean useDefaultFilters) {
this.includeFilters.clear();
this.excludeFilters.clear();
}
/**
* 扫描指定路径指定注解的类
* @param basePackage
* @param annotations
* @return
*/
public static Set<Class> scan(String basePackage, Class<? extends Annotation>... annotations) {
ClassScanner classScanner = new ClassScanner();
for (Class<? extends Annotation> annotation : annotations) {
classScanner.addIncludeFilter(new AnnotationTypeFilter(annotation));
}
return classScanner.doScan(basePackage);
}
/**
* 扫描多个路径下包含指定注解的类
* @param basePackages
* @param annotations
* @return
*/
public static Set<Class> scan(String[] basePackages, Class<? extends Annotation>... annotations) {
ClassScanner classScanner = new ClassScanner();
for (Class<? extends Annotation> annotation : annotations) {
classScanner.addIncludeFilter(new AnnotationTypeFilter(annotation));
}
Set<Class> classes = new HashSet<>();
for (String basePackage : basePackages) {
classes.addAll(classScanner.doScan(basePackage));
}
return classes;
}
/**
* 扫描指定路径下的类信息
* @param basePackage
* @return
*/
public Set<Class> doScan(String basePackage) {
Set<Class> classes = new HashSet<>();
// 扫描路径
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
+ ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.resolvePlaceholders(basePackage))
+ "/**/*.class";
try {
// 获取指定扫描路径的资源
Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
for (Resource resource : resources) {
if (resource.isReadable()) {
MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
if ((this.includeFilters.size() == 0 && this.excludeFilters.size() == 0) || matches(metadataReader)) {
try {
// 返回符合条件的资源
classes.add(Class.forName(metadataReader.getClassMetadata().getClassName()));
} catch (ClassNotFoundException e) {
log.error("class forName 异常:", e);
}
}
}
}
} catch (IOException e) {
log.error("扫描加载资源io异常:", e);
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", e);
}
return classes;
}
/**
* 资源是否匹配
* @param metadataReader
* @return
* @throws IOException
*/
private boolean matches(MetadataReader metadataReader) throws IOException {
for (TypeFilter excludeFilter : this.excludeFilters) {
if (excludeFilter.match(metadataReader, this.metadataReaderFactory)) {
return false;
}
}
for (TypeFilter includeFilter : this.includeFilters) {
if (includeFilter.match(metadataReader, this.metadataReaderFactory)) {
return true;
}
}
return false;
}
}
- SpringContextUtil
@Getter
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtil.applicationContext = applicationContext;
}
public static <T> T getBean(String beanName) {
return (T) applicationContext.getBean(beanName);
}
public static <T> T getBean(Class<T> requireType) {
return applicationContext.getBean(requireType);
}
}
- HandlerProcessor 扫描指定路径下的实现 Bean,加载到上下文中
@Component
public class HandlerProcessor implements BeanFactoryPostProcessor {
public static final String HANDLER_PACKAGE = "com.trade.service.strategy.impl";
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Map<String, Class> handlerMap = Maps.newHashMapWithExpectedSize(4);
ClassScanner.scan(HANDLER_PACKAGE, OrderType.class).forEach(clazz -> {
// 获取注解中的类型值
OrderType orderType = (OrderType) clazz.getAnnotation(OrderType.class);
String type = orderType.value();
// 将注解中的类型值作为 key,对应类作为 value 保存在 Map 中
handlerMap.put(type, clazz);
});
// 初始化 HandlerContext,将其注册到 spring 容器中
HandlerContext context = new HandlerContext(handlerMap);
beanFactory.registerSingleton(HandlerContext.class.getName(), context);
}
}
- HandlerContext
public class HandlerContext {
private Map<String, Class> handlerMap;
public HandlerContext(Map<String, Class> handlerMap) {
this.handlerMap = handlerMap;
}
/**
* 获取对应交易类型的处理类
* @param type
* @return
*/
public AbstractHandler getInstance(String type) {
Class clazz = handlerMap.get(type);
if (clazz == null) {
throw new IllegalArgumentException("未找到订单类型【" + type + "】的处理类");
}
return (AbstractHandler) SpringContextUtil.getBean(clazz);
}
}
- OrderType
@Documented
@Inherited
@Retention(value = RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
public @interface OrderType {
String value() default "";
}
网友评论