mirror of
https://gitee.com/easii/mapstruct-plus.git
synced 2025-12-06 17:18:43 +08:00
modified the approach to avoid circular dependencies.
This commit is contained in:
parent
b12cd2b14a
commit
9bfe62a0c2
@ -180,6 +180,7 @@ public class AutoMapperProcessor extends AbstractProcessor {
|
||||
// 根据配置生成适配类生成器
|
||||
switch (AutoMapperProperties.getComponentModel()) {
|
||||
case MappingConstants.ComponentModel.SPRING:
|
||||
case ContextConstants.ComponentModelConfig.springLazy:
|
||||
this.adapterMapperGenerator = new SpringAdapterMapperGenerator();
|
||||
break;
|
||||
case ComponentModelConstant.SOLON:
|
||||
|
||||
@ -7,12 +7,12 @@ import com.squareup.javapoet.JavaFile;
|
||||
import com.squareup.javapoet.MethodSpec;
|
||||
import com.squareup.javapoet.ParameterSpec;
|
||||
import com.squareup.javapoet.ParameterizedTypeName;
|
||||
import com.squareup.javapoet.TypeName;
|
||||
import com.squareup.javapoet.TypeSpec;
|
||||
import io.github.linpeilie.processor.ContextConstants;
|
||||
import io.github.linpeilie.processor.metadata.AutoMapperMetadata;
|
||||
import io.github.linpeilie.processor.metadata.AutoMappingMetadata;
|
||||
import io.github.linpeilie.utils.CollectionUtils;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@ -55,7 +55,7 @@ public class AutoMapperGenerator {
|
||||
JavaFile.builder(metadata.mapperPackage(), createTypeSpec(processingEnv, metadata, mapperName))
|
||||
.build()
|
||||
.writeTo(writer);
|
||||
} catch (IOException e) {
|
||||
} catch (Exception e) {
|
||||
processingEnv.getMessager()
|
||||
.printMessage(ERROR,
|
||||
"Error while opening " + metadata.mapperName() + " output file: " + e.getMessage());
|
||||
@ -79,19 +79,69 @@ public class AutoMapperGenerator {
|
||||
ParameterSpec target = ParameterSpec.builder(targetClassName, "target")
|
||||
.addAnnotation(AnnotationSpec.builder(ClassName.get("org.mapstruct", "MappingTarget")).build())
|
||||
.build();
|
||||
ParameterSpec sourceList = ParameterSpec.builder(
|
||||
ParameterizedTypeName.get(
|
||||
ClassName.get("java.util", "List"),
|
||||
metadata.getSourceClassName()
|
||||
), "sourceList").build();
|
||||
ParameterSpec context =
|
||||
ParameterSpec.builder(ClassName.get("io.github.linpeilie", "CycleAvoidingMappingContext"), "context")
|
||||
.addAnnotation(ClassName.get("org.mapstruct", "Context"))
|
||||
.build();
|
||||
if (metadata.getFieldMappingList() != null && !metadata.getFieldMappingList().isEmpty()) {
|
||||
builder.addMethod(addConvertMethodSpec(
|
||||
metadata.isCycleAvoiding() ? CollectionUtils.newArrayList(source, context) : Collections.singletonList(
|
||||
source),
|
||||
metadata.getFieldMappingList(),
|
||||
targetClassName,
|
||||
CONVERT_METHOD_NAME));
|
||||
ParameterizedTypeName targetList = ParameterizedTypeName.get(
|
||||
ClassName.get("java.util", "List"),
|
||||
targetClassName
|
||||
);
|
||||
|
||||
// 如果需要避免循环依赖,则把 BaseMapper 中的实现,全部添加 DoIgnore 防止使用该方法进行转换
|
||||
if (metadata.isCycleAvoiding()) {
|
||||
// convert(source)
|
||||
builder.addMethod(
|
||||
addCallSuperConvertMethodSpec(
|
||||
metadata.getSuperClass(),
|
||||
CollectionUtils.newArrayList(source),
|
||||
targetClassName,
|
||||
CONVERT_METHOD_NAME)
|
||||
);
|
||||
// convert(source, target)
|
||||
builder.addMethod(
|
||||
addCallSuperConvertMethodSpec(
|
||||
metadata.getSuperClass(), CollectionUtils.newArrayList(source, target),
|
||||
targetClassName,
|
||||
CONVERT_METHOD_NAME
|
||||
)
|
||||
);
|
||||
// convert(sourceList)
|
||||
builder.addMethod(
|
||||
addCallSuperConvertMethodSpec(
|
||||
metadata.getSuperClass(), CollectionUtils.newArrayList(sourceList),
|
||||
targetList,
|
||||
CONVERT_METHOD_NAME
|
||||
)
|
||||
);
|
||||
// convert(sourceList, context)
|
||||
builder.addMethod(
|
||||
addCallSuperConvertMethodSpec(
|
||||
metadata.getSuperClass(), CollectionUtils.newArrayList(sourceList, context),
|
||||
targetList,
|
||||
CONVERT_METHOD_NAME
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// convert(source) | convert(source, context)
|
||||
if (CollectionUtils.isNotEmpty(metadata.getFieldMappingList()) || metadata.isCycleAvoiding()) {
|
||||
builder.addMethod(addConvertMethodSpec(
|
||||
metadata.isCycleAvoiding()
|
||||
? CollectionUtils.newArrayList(source, context)
|
||||
: Collections.singletonList(source),
|
||||
metadata.getFieldMappingList(),
|
||||
targetClassName,
|
||||
CONVERT_METHOD_NAME,
|
||||
metadata.isCycleAvoiding()));
|
||||
}
|
||||
|
||||
// convert(source, target)
|
||||
boolean targetIsImmutable = classIsImmutable(processingEnv, targetClassName);
|
||||
if (targetIsImmutable) {
|
||||
builder.addMethod(
|
||||
@ -100,13 +150,15 @@ public class AutoMapperGenerator {
|
||||
context) : CollectionUtils.newArrayList(source, target),
|
||||
targetClassName,
|
||||
CONVERT_METHOD_NAME));
|
||||
} else if (metadata.getFieldMappingList() != null && !metadata.getFieldMappingList().isEmpty()) {
|
||||
} else if (CollectionUtils.isNotEmpty(metadata.getFieldMappingList()) || metadata.isCycleAvoiding()) {
|
||||
builder.addMethod(addConvertMethodSpec(
|
||||
metadata.isCycleAvoiding() ? CollectionUtils.newArrayList(source, target,
|
||||
context) : CollectionUtils.newArrayList(source, target),
|
||||
metadata.isCycleAvoiding()
|
||||
? CollectionUtils.newArrayList(source, target, context)
|
||||
: CollectionUtils.newArrayList(source, target),
|
||||
metadata.getFieldMappingList(),
|
||||
targetClassName,
|
||||
CONVERT_METHOD_NAME));
|
||||
CONVERT_METHOD_NAME,
|
||||
metadata.isCycleAvoiding()));
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
@ -137,15 +189,50 @@ public class AutoMapperGenerator {
|
||||
|
||||
private MethodSpec addConvertMethodSpec(List<ParameterSpec> parameterSpecs,
|
||||
List<AutoMappingMetadata> autoMappingMetadataList,
|
||||
ClassName target, String methodName) {
|
||||
ClassName target,
|
||||
String methodName,
|
||||
boolean cycleAvoiding) {
|
||||
final MethodSpec.Builder methodSpecBuilder = MethodSpec.methodBuilder(methodName)
|
||||
.addParameters(parameterSpecs)
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
|
||||
.addAnnotation(ClassName.get(ContextConstants.DoIgnore.packageName, ContextConstants.DoIgnore.className))
|
||||
.returns(target);
|
||||
if (CollectionUtils.isNotEmpty(autoMappingMetadataList)) {
|
||||
methodSpecBuilder.addAnnotations(buildMappingAnnotations(autoMappingMetadataList));
|
||||
}
|
||||
if (cycleAvoiding) {
|
||||
methodSpecBuilder.addAnnotation(
|
||||
ClassName.get(ContextConstants.DoIgnore.packageName, ContextConstants.DoIgnore.className));
|
||||
}
|
||||
return methodSpecBuilder.build();
|
||||
}
|
||||
|
||||
private ClassName doIgnore() {
|
||||
return ClassName.get(ContextConstants.DoIgnore.packageName, ContextConstants.DoIgnore.className);
|
||||
}
|
||||
|
||||
private MethodSpec addCallSuperConvertMethodSpec(ClassName superClass,
|
||||
List<ParameterSpec> parameterSpecs,
|
||||
TypeName target,
|
||||
String methodName) {
|
||||
MethodSpec.Builder methodSpecBuilder = MethodSpec.methodBuilder(methodName)
|
||||
.addParameters(parameterSpecs)
|
||||
.addModifiers(Modifier.DEFAULT, Modifier.PUBLIC)
|
||||
.addAnnotation(doIgnore())
|
||||
.returns(target);
|
||||
|
||||
// return super.convert( *** );
|
||||
CodeBlock.Builder codeBlock = CodeBlock.builder();
|
||||
codeBlock.add("return $T.super.$L(", superClass, methodName);
|
||||
for (int i = 0; i < parameterSpecs.size(); i++) {
|
||||
codeBlock.add("$N", parameterSpecs.get(i));
|
||||
if (i != parameterSpecs.size() -1) {
|
||||
codeBlock.add(",");
|
||||
}
|
||||
}
|
||||
codeBlock.add(");\n");
|
||||
|
||||
methodSpecBuilder.addCode(codeBlock.build());
|
||||
|
||||
return methodSpecBuilder.build();
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package io.github.linpeilie;
|
||||
|
||||
import io.github.linpeilie.annotations.DoIgnore;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import org.mapstruct.Context;
|
||||
@ -8,13 +7,10 @@ import org.mapstruct.MappingTarget;
|
||||
|
||||
public interface BaseCycleAvoidingMapper<S, T> extends BaseMapper<S, T> {
|
||||
|
||||
@DoIgnore
|
||||
T convert(S source, @Context CycleAvoidingMappingContext context);
|
||||
|
||||
@DoIgnore
|
||||
T convert(S source, @MappingTarget T target, @Context CycleAvoidingMappingContext context);
|
||||
|
||||
@DoIgnore
|
||||
default List<T> convert(List<S> sourceList, @Context CycleAvoidingMappingContext context) {
|
||||
return sourceList.stream()
|
||||
.map(item -> convert(item, context))
|
||||
@ -22,20 +18,17 @@ public interface BaseCycleAvoidingMapper<S, T> extends BaseMapper<S, T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@DoIgnore
|
||||
default T convert(S source) {
|
||||
return convert(source, new CycleAvoidingMappingContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
@DoIgnore
|
||||
default T convert(S source, @MappingTarget T target) {
|
||||
return convert(source, new CycleAvoidingMappingContext());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@DoIgnore
|
||||
default List<T> convert(List<S> sourceList) {
|
||||
return convert(sourceList, new CycleAvoidingMappingContext());
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package io.github.linpeilie;
|
||||
|
||||
import io.github.linpeilie.annotations.DoIgnore;
|
||||
import io.github.linpeilie.utils.CollectionUtils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -9,13 +8,10 @@ import org.mapstruct.MappingTarget;
|
||||
|
||||
public interface BaseMapper<S, T> {
|
||||
|
||||
@DoIgnore
|
||||
T convert(S source);
|
||||
|
||||
@DoIgnore
|
||||
T convert(S source, @MappingTarget T target);
|
||||
|
||||
@DoIgnore
|
||||
default List<T> convert(List<S> sourceList) {
|
||||
if (CollectionUtils.isEmpty(sourceList)) {
|
||||
return new ArrayList<>();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user