情况说明
项目中有一个文件管理模块,供用户创建文件夹,上传文件来管理文件。故此想把其他模块的文件统一维护到文件管理模块,根据注解中的path参数保存到相应的位置
问题
无法切入到对应的dataManage.save,想问一下来自依赖的类是无法切入吗,还是我的用法有问题呢?
代码
FileSync
/**
* @author rockm3
* 注解只能使用在类/接口/枚举
* RetentionPolicy.RUNTIME:运行级别保留,编译后的class文件中存在,在jvm运行时保留,可以被反射调用。
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface FileSync {
// 保存路径
String path();
}
FileSyncAspect
@Aspect
@Component
public class FileSyncAspect {
private static final Logger log = org.slf4j.LoggerFactory.getLogger(FileSyncAspect.class);
private Integer argsNum = -1;
@Autowired
private Metadata metadata;
@Autowired
private DataManager dataManager;
/**
* 保存或更新切点
* */
@Pointcut("execution(* io.jmix.core.impl.DataManagerImpl.save(..))")
public void savePoint(){
}
/**
* 删除切点
* */
@Pointcut("execution(* io.jmix.core.impl.DataManagerImpl.remove(..))")
public void removePoint(){
}
/**
* 前置通知
* */
@Before(value = "savePoint()")
public void beforeSave(JoinPoint jp) {
// 获取签名
Signature signature = jp.getSignature();
// 转为方法签名
MethodSignature msg=(MethodSignature) signature;
// 反射获取目标对象
Object target = jp.getTarget();
try {
// 获取目标方法
Method method = target.getClass().getMethod(msg.getName(), msg.getParameterTypes());
Class<?>[] parameterTypes = method.getParameterTypes();
this.argsNum = parameterTypes.length;
if (parameterTypes.length == 1) {
// 参数类型是SaveContext
if (parameterTypes[0].equals(SaveContext.class)) {
this.argsNum = 0;
}
}
} catch (Exception ignored) {
}
}
/**
* 返回通知
* */
@AfterReturning(value = "savePoint()", returning = "result")
public void afterReturningSave(JoinPoint jp, Object result) {
// 转存时使用save方法跳过转存检测
if (result.getClass().equals(File.class)) {
return;
}
if (this.argsNum > 0) {
if (this.argsNum == 1) {
List<Map<String,Object>> fileRefs = getFileRef(result);
// 遍历保存
if (fileRefs.size()>0) {
for (Map<String,Object> record:fileRefs) {
saveFileRef(record);
}
}
}
} else if (this.argsNum == 0) {
Object[] args = jp.getArgs();
SaveContext saveContext = (SaveContext) args[0];
Set<Object> entities = saveContext.getEntitiesToSave();
saveFileRefAll(entities);
}
}
/**
* 异常通知
* */
@AfterThrowing(value = "savePoint()", throwing = "e")
public void afterThrowingSave(JoinPoint jp, Exception e) {
String name = jp.getSignature().getName();
log.info(name + "方法抛异常了,异常是:" + e.getMessage());
}
/**
* 实体对象转成Map
* @param obj 实体对象
*/
public static Map<String, Object> objectToMap(Object obj) {
Map<String, Object> map = new HashMap<>();
if (obj == null) {
return map;
}
Class<?> clazz = obj.getClass();
Field[] fields = clazz.getDeclaredFields();
try {
for (Field field : fields) {
field.setAccessible(true);
map.put(field.getName(), field.get(obj));
}
} catch (Exception e) {
log.error("Error", e);
}
return map;
}
/**
* @param entity 输入实体对象
* @return 返回需要同步的文件对象和需要保存的路径
* */
private List<Map<String,Object>> getFileRef(Object entity) {
MetaClass metaClass = metadata.getClass(entity);
List<Map<String,Object>> fileRefs = new ArrayList<>();
// 获取所有字段信息
Collection<MetaProperty> allProperties = metaClass.getOwnProperties();
for (MetaProperty record:allProperties) {
// 定位到FileRef的位置
if (record.getJavaType().equals(FileRef.class)) {
// 获取当前字段的所有注解
Annotation[] annotations = record.getAnnotatedElement().getAnnotations();
// 遍历注解 寻找FileSync
for (Annotation annotation:annotations) {
// 取到FileSync注解
if (annotation.annotationType().equals(FileSync.class)) {
// 强转
FileSync fileSync = (FileSync) annotation;
// 获取注解path值
String path = fileSync.path();
Map<String,Object> fileRef = new HashMap<>();
// 写入路径
fileRef.put("path",path);
// 写入字段名
fileRef.put("fieldName",record.getName());
fileRefs.add(fileRef);
break;
}
}
}
}
// 强转获取实体的对应map
Map<String, Object> resultMap = objectToMap(entity);
if (fileRefs.size()>0) {
Iterator<Map<String,Object>> iterator = fileRefs.iterator();
while (iterator.hasNext()) {
Map<String,Object> record = iterator.next();
String fieldName = (String) record.get("fieldName");
Object fieldValue = resultMap.get(fieldName);
if (fieldValue.getClass().equals(FileRef.class)) {
record.put("fieldValue",fieldValue);
} else {
iterator.remove();
}
}
}
return fileRefs;
}
private void saveFileRef(Map<String, Object> record) {
String path = (String) record.get("path");
FileRef fileRef = (FileRef) record.get("fieldValue");
// 检查path是否存在 不存在就创建
String[] splitPath = path.split("/");
FileFolder parentFileFolder = null;
for (String s:splitPath) {
try {
parentFileFolder = dataManager
.load(FileFolder.class)
.query("select e from ef_FileFolder e where e.fileFolderName = :fileFolderName")
.parameter("fileFolderName",s)
.one();
} catch (Exception ignored) {
FileFolder fileFolder = dataManager.create(FileFolder.class);
fileFolder.setFileFolderName(s);
fileFolder.setCanDel(false);
if (parentFileFolder == null) {
dataManager.save(fileFolder);
} else {
fileFolder.setParentFileFolder(parentFileFolder);
dataManager.save(parentFileFolder,fileFolder);
}
parentFileFolder = fileFolder;
}
}
// 更新或者新建
// 更新
try {
assert parentFileFolder != null;
File file = dataManager
.load(File.class)
.query("select e from ef_File e where e.file = :file and e.fileFolder = :fileFolder")
.parameter("file", fileRef)
.parameter("fileFolder", parentFileFolder)
.one();
} catch (Exception ignored) {
// 新建
File file = dataManager.create(File.class);
file.setFile(fileRef);
file.setFileFolder(parentFileFolder);
dataManager.save(file,parentFileFolder);
}
}
private void saveFileRefAll(Set<Object> entities) {
for (Object entity:entities) {
if (entity.getClass().equals(File.class)) {
continue;
}
List<Map<String,Object>> fileRefs = getFileRef(entity);
// 遍历保存
if (fileRefs.size()>0) {
for (Map<String,Object> record:fileRefs) {
saveFileRef(record);
}
}
}
}
}
File
@Column(name = "FILE_", length = 1024)
@FileSync(path = "/航迹回放")
private FileRef file;