package com.github.wxiaoqi.merge.core;
import com.github.wxiaoqi.merge.annonation.MergeField;
import com.github.wxiaoqi.merge.annonation.MergeResult;
import com.github.wxiaoqi.merge.configuration.MergeProperties;
import com.github.wxiaoqi.merge.facade.DefaultMergeResultParser;
import com.github.wxiaoqi.merge.facade.IMergeResultParser;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* @author ace
* @create 2018/2/2.
*/
@Slf4j
public class MergeCore {
private Map<String, MergeField> mergeFieldMap;
private ListeningExecutorService backgroundRefreshPools;
private LoadingCache<String, Map<String, String>> caches;
public MergeCore(MergeProperties mergeProperties) {
this.backgroundRefreshPools =
MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(mergeProperties.getGuavaCacheRefreshThreadPoolSize()));
this.mergeFieldMap = new HashMap<String, MergeField>();
this.caches = CacheBuilder.newBuilder()
.maximumSize(mergeProperties.getGuavaCacheNumMaxSize())
.refreshAfterWrite(mergeProperties.getGuavaCacheRefreshWriteTime(), TimeUnit.MINUTES)
.build(new CacheLoader<String, Map<String, String>>() {
@Override
public Map<String, String> load(String key) throws Exception {
log.debug("首次读取缓存: " + key);
MergeField mergeField = mergeFieldMap.get(key);
Object bean = BeanFactoryUtils.getBean(mergeField.feign());
Method method = mergeField.feign().getMethod(mergeField.method(), String.class);
Map<String, String> invoke = (Map<String, String>) method.invoke(bean, mergeField.key());
return invoke;
}
@Override
public ListenableFuture<Map<String, String>> reload(final String key,
Map<String, String> oldValue) throws Exception {
return backgroundRefreshPools.submit(() -> {
log.debug("异步刷新缓存: " + key);
MergeField mergeField = mergeFieldMap.get(key);
Object bean = BeanFactoryUtils.getBean(mergeField.feign());
Method method = mergeField.feign().getMethod(mergeField.method(), String.class);
Map<String, String> invoke = (Map<String, String>) method.invoke(bean, mergeField.key());
return invoke;
});
}
});
}
/**
* aop方式加工
*
* @param pjp
* @param anno
* @return
* @throws Throwable
*/
public Object mergeData(ProceedingJoinPoint pjp, MergeResult anno) throws Throwable {
Object proceed = pjp.proceed();
try {
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method m = signature.getMethod();
ParameterizedType parameterizedType = (ParameterizedType) m.getGenericReturnType();
Type rawType = parameterizedType.getRawType();
List<?> result = null;
// 获取当前方法的返回值
Type[] types = parameterizedType.getActualTypeArguments();
Class clazz = ((Class) types[0]);
// 非list直接返回
if (anno.resultParser().equals(DefaultMergeResultParser.class) && ((Class) rawType).isAssignableFrom(List.class)) {
result = (List<?>) proceed;
mergeResult(clazz, result);
return result;
} else {
IMergeResultParser bean = BeanFactoryUtils.getBean(anno.resultParser());
result = bean.parser(proceed);
mergeResult(clazz, result);
return proceed;
}
} catch (Exception e) {
log.error("某属性数据聚合失败", e);
return proceed;
}
}
/**
* 手动调用进行配置合并
*
* @param clazz
* @param result
* @throws ExecutionException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public void mergeResult(Class clazz, List<?> result) throws ExecutionException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Field[] fields = clazz.getDeclaredFields();
List<Field> mergeFields = new ArrayList<Field>();
Map<String, Map<String, String>> invokes = new HashMap<>();
String className = clazz.getName();
// 获取属性
for (Field field : fields) {
MergeField annotation = field.getAnnotation(MergeField.class);
if (annotation != null) {
mergeFields.add(field);
String args = annotation.key();
// 表示该属性需要将值聚合成条件远程查询
if (annotation.isValueNeedMerge()) {
StringBuffer sb = new StringBuffer("");
Set<String> ids = new HashSet<>();
result.stream().forEach(obj -> {
field.setAccessible(true);
Object o = null;
try {
o = field.get(obj);
if (o != null) {
if (!ids.contains(o)) {
ids.add(o.toString());
sb.append(o.toString()).append(",");
}
}
} catch (IllegalAccessException e) {
log.error("数据属性加工失败:" + field, e);
throw new RuntimeException("数据属性加工失败:" + field, e);
}
});
args = sb.substring(0, sb.length() - 1);
} else {
String key = className + field.getName();
mergeFieldMap.put(key, annotation);
// 从缓存获取
Map<String, String> value =
(Map<String, String>) caches.get(key);
if (value != null) {
invokes.put(field.getName(), value);
continue;
}
}
Object bean = BeanFactoryUtils.getBean(annotation.feign());
Method method = annotation.feign().getMethod(annotation.method(), String.class);
Map<String, String> value = (Map<String, String>) method.invoke(bean, args);
invokes.put(field.getName(), value);
}
}
result.stream().forEach(obj -> {
mergeObjFieldValue(obj, mergeFields, invokes);
});
}
/**
* 手动对单个结果进行配置合并
*
* @param clazz
* @param mergeObj
* @throws ExecutionException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public void mergeOne(Class clazz, Object mergeObj) throws ExecutionException, NoSuch
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
解决Spring Cloud服务拆分后分页数据的属性或单个对象的属性拆分之痛, 支持对静态数据属性(数据字典)、动态主键数据进行自动注入和转化, 其中聚合的静态数据会进行一级混存(guava).如两个服务,A服务的某张表用到了B服务的某张表的值,我们在对A服务那张表查询的时候,把B服务某张表的值聚合在A服务的那次查询过程中
资源推荐
资源详情
资源评论
收起资源包目录
Cloud-Merge-master.zip (30个子文件)
Cloud-Merge-master
pom.xml 2KB
LICENSE 10KB
ace-merge-core
pom.xml 1KB
src
main
java
com
github
wxiaoqi
merge
EnableAceMerge.java 400B
configuration
MergeAutoConfiguration.java 1KB
MergeProperties.java 1KB
aspect
MergeAspect.java 1KB
core
MergeCore.java 11KB
BeanFactoryUtils.java 1KB
annonation
MergeField.java 785B
MergeResult.java 598B
facade
DefaultMergeResultParser.java 287B
IMergeResultParser.java 312B
ace-merge-demo
ace-data-merge-demo
pom.xml 1KB
src
main
resources
application.yml 498B
java
com
github
wxiaoqi
ace
merge
demo
DemoBootstrap.java 655B
rest
UserRest.java 1011B
feign
IDataFeign.java 587B
biz
UserBiz.java 2KB
entity
User.java 1KB
merge
TestMergeResultParser.java 386B
ace-data-provider
pom.xml 885B
src
main
resources
application.yml 281B
java
com
github
wxiaoqi
ace
merge
provider
rest
DataRest.java 1KB
ProviderBootstrap.java 473B
pom.xml 1KB
ace-eureka
pom.xml 726B
src
main
resources
application.yml 329B
java
com
github
wxiaoqi
ace
merge
center
CenterBootstrap.java 2KB
.gitignore 68B
共 30 条
- 1
资源评论
Java程序员-张凯
- 粉丝: 1w+
- 资源: 6705
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- OpenCV计算机视觉实战(Python版):资料+课件
- OpenCV+TensorFlow 入门人工智能图像处理: 课程源码
- 低碳城市试点政策名单及程序处理
- Wind研发支出数据大全2006-2022年[包含费用化-资本化-研发人员]
- 2022研发创新、创新投入、研发投入、研发支出、研发人员
- 更新2011-2021沪深A股上市公司数字化转型指数(面板数据格式、含公式)
- I2C接口18路LED呼吸灯驱动IS31FL3218互相替代SN3218替换HTR3218
- 重磅2022-2000年中国地级市城市促进科技和金融结合试点政策数据
- 使用Python和Pytorch框架,基于CNN模型开发的图像识别系统
- 中国居民消费支出数据(1952-2022)
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功