From 9ee817b2a12d512d5a986bbcaaf3480bcf936012 Mon Sep 17 00:00:00 2001 From: linpeilie Date: Wed, 26 Jun 2024 00:07:26 +0800 Subject: [PATCH 01/13] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Spring=E5=BB=B6?= =?UTF-8?q?=E8=BF=9F=E5=8A=A0=E8=BD=BD=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../linpeilie/processor/ContextConstants.java | 3 +- .../SpringDelayInjectMapperReference.java | 25 ++++++++++ .../processor/SpringComponentProcessor.java | 48 +++++++++++++++++++ ...p.internal.processor.ModelElementProcessor | 1 + .../SpringDelayInjectMapperReference.ftl | 2 + .../mapstruct/MapstructAutoConfiguration.java | 5 ++ .../mapstruct/SpringContextUtils.java | 20 ++++++++ 7 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/enhance/model/SpringDelayInjectMapperReference.java create mode 100644 mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/enhance/processor/SpringComponentProcessor.java create mode 100644 mapstruct-plus-processor/src/main/resources/io/github/linpeilie/processor/enhance/model/SpringDelayInjectMapperReference.ftl create mode 100644 mapstruct-plus-spring-boot-starter/src/main/java/io/github/linpeilie/mapstruct/SpringContextUtils.java diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/ContextConstants.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/ContextConstants.java index 7344696..14013b4 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/ContextConstants.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/ContextConstants.java @@ -65,7 +65,8 @@ public interface ContextConstants { interface ComponentModelConfig { String qualifiedClassName = "io.github.linpeilie.annotations.ComponentModelConfig"; - String defaultComponentModel = MappingConstants.ComponentModel.SPRING; + String springLazy = "spring-lazy"; + String defaultComponentModel = springLazy; } interface ConvertAdapter { diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/enhance/model/SpringDelayInjectMapperReference.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/enhance/model/SpringDelayInjectMapperReference.java new file mode 100644 index 0000000..a2b5d2d --- /dev/null +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/enhance/model/SpringDelayInjectMapperReference.java @@ -0,0 +1,25 @@ +package io.github.linpeilie.processor.enhance.model; + +import io.github.linpeilie.processor.enhance.processor.SpringComponentProcessor; +import java.util.HashSet; +import java.util.Set; +import org.mapstruct.ap.internal.model.MapperReference; +import org.mapstruct.ap.internal.model.common.Type; + +public class SpringDelayInjectMapperReference extends MapperReference { + + private final Type springContextUtil; + + public SpringDelayInjectMapperReference(Type type, String variableName, boolean isUsed, Type springContextUtil) { + super(type, variableName, isUsed); + this.springContextUtil = springContextUtil; + } + + @Override + public Set getImportTypes() { + Set importTypes = new HashSet<>(); + importTypes.add(getType()); + importTypes.add(springContextUtil); + return importTypes; + } +} diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/enhance/processor/SpringComponentProcessor.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/enhance/processor/SpringComponentProcessor.java new file mode 100644 index 0000000..8d74245 --- /dev/null +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/enhance/processor/SpringComponentProcessor.java @@ -0,0 +1,48 @@ +package io.github.linpeilie.processor.enhance.processor; + +import io.github.linpeilie.processor.ContextConstants; +import io.github.linpeilie.processor.enhance.model.SpringDelayInjectMapperReference; +import io.github.linpeilie.utils.CollectionUtils; +import java.util.Collections; +import java.util.List; +import org.mapstruct.ap.internal.gem.InjectionStrategyGem; +import org.mapstruct.ap.internal.model.Annotation; +import org.mapstruct.ap.internal.model.Field; +import org.mapstruct.ap.internal.model.Mapper; +import org.mapstruct.ap.internal.processor.AnnotationBasedComponentModelProcessor; + +public class SpringComponentProcessor extends AnnotationBasedComponentModelProcessor { + + private Annotation component() { + return new Annotation(getTypeFactory().getType("org.springframework.stereotype.Component")); + } + + @Override + protected String getComponentModelIdentifier() { + return ContextConstants.ComponentModelConfig.springLazy; + } + + @Override + protected List getTypeAnnotations(Mapper mapper) { + return CollectionUtils.newArrayList(component()); + } + + @Override + protected List getMapperReferenceAnnotations() { + return Collections.emptyList(); + } + + @Override + protected boolean requiresGenerationOfDecoratorClass() { + return true; + } + + @Override + protected Field replacementMapperReference(Field originalReference, + List annotations, + InjectionStrategyGem injectionStrategy) { + return new SpringDelayInjectMapperReference(originalReference.getType(), originalReference.getVariableName(), + originalReference.isUsed(), + getTypeFactory().getType("io.github.linpeilie.mapstruct.SpringContextUtils")); + } +} diff --git a/mapstruct-plus-processor/src/main/resources/META-INF/services/org.mapstruct.ap.internal.processor.ModelElementProcessor b/mapstruct-plus-processor/src/main/resources/META-INF/services/org.mapstruct.ap.internal.processor.ModelElementProcessor index a144912..98cd7a9 100644 --- a/mapstruct-plus-processor/src/main/resources/META-INF/services/org.mapstruct.ap.internal.processor.ModelElementProcessor +++ b/mapstruct-plus-processor/src/main/resources/META-INF/services/org.mapstruct.ap.internal.processor.ModelElementProcessor @@ -12,3 +12,4 @@ org.mapstruct.ap.internal.processor.MethodRetrievalProcessor org.mapstruct.ap.internal.processor.SpringComponentProcessor org.mapstruct.ap.internal.processor.MapperServiceProcessor io.github.linpeilie.processor.solon.SolonComponentProcessor +io.github.linpeilie.processor.enhance.processor.SpringComponentProcessor diff --git a/mapstruct-plus-processor/src/main/resources/io/github/linpeilie/processor/enhance/model/SpringDelayInjectMapperReference.ftl b/mapstruct-plus-processor/src/main/resources/io/github/linpeilie/processor/enhance/model/SpringDelayInjectMapperReference.ftl new file mode 100644 index 0000000..894e219 --- /dev/null +++ b/mapstruct-plus-processor/src/main/resources/io/github/linpeilie/processor/enhance/model/SpringDelayInjectMapperReference.ftl @@ -0,0 +1,2 @@ +<#-- @ftlvariable name="" type="io.github.linpeilie.processor.enhance.model.SpringDelayInjectMapperReference" --> +private <@includeModel object=type/> ${variableName} = SpringContextUtils.getBean(<@includeModel object=type/>.class); \ No newline at end of file diff --git a/mapstruct-plus-spring-boot-starter/src/main/java/io/github/linpeilie/mapstruct/MapstructAutoConfiguration.java b/mapstruct-plus-spring-boot-starter/src/main/java/io/github/linpeilie/mapstruct/MapstructAutoConfiguration.java index 23743f5..28c7a06 100644 --- a/mapstruct-plus-spring-boot-starter/src/main/java/io/github/linpeilie/mapstruct/MapstructAutoConfiguration.java +++ b/mapstruct-plus-spring-boot-starter/src/main/java/io/github/linpeilie/mapstruct/MapstructAutoConfiguration.java @@ -24,4 +24,9 @@ public class MapstructAutoConfiguration { return new Converter(converterFactory); } + @Bean + public SpringContextUtils springContextUtils() { + return new SpringContextUtils(); + } + } diff --git a/mapstruct-plus-spring-boot-starter/src/main/java/io/github/linpeilie/mapstruct/SpringContextUtils.java b/mapstruct-plus-spring-boot-starter/src/main/java/io/github/linpeilie/mapstruct/SpringContextUtils.java new file mode 100644 index 0000000..b34275f --- /dev/null +++ b/mapstruct-plus-spring-boot-starter/src/main/java/io/github/linpeilie/mapstruct/SpringContextUtils.java @@ -0,0 +1,20 @@ +package io.github.linpeilie.mapstruct; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +public class SpringContextUtils implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + SpringContextUtils.applicationContext = applicationContext; + } + + public static T getBean(Class clazz) { + return applicationContext.getBean(clazz); + } + +} -- Gitee From 9d233506f5fd8fcb8918aa8e44e851c81296fda9 Mon Sep 17 00:00:00 2001 From: linpeilie Date: Wed, 26 Jun 2024 11:12:59 +0800 Subject: [PATCH 02/13] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20SolonComponentProces?= =?UTF-8?q?sor=20=E6=89=80=E5=9C=A8=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{solon => enhance/processor}/SolonComponentProcessor.java | 2 +- .../org.mapstruct.ap.internal.processor.ModelElementProcessor | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/{solon => enhance/processor}/SolonComponentProcessor.java (95%) diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/solon/SolonComponentProcessor.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/enhance/processor/SolonComponentProcessor.java similarity index 95% rename from mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/solon/SolonComponentProcessor.java rename to mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/enhance/processor/SolonComponentProcessor.java index 4c6aa63..1c4fd8c 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/solon/SolonComponentProcessor.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/enhance/processor/SolonComponentProcessor.java @@ -1,4 +1,4 @@ -package io.github.linpeilie.processor.solon; +package io.github.linpeilie.processor.enhance.processor; import io.github.linpeilie.ComponentModelConstant; import io.github.linpeilie.utils.CollectionUtils; diff --git a/mapstruct-plus-processor/src/main/resources/META-INF/services/org.mapstruct.ap.internal.processor.ModelElementProcessor b/mapstruct-plus-processor/src/main/resources/META-INF/services/org.mapstruct.ap.internal.processor.ModelElementProcessor index 98cd7a9..42fded8 100644 --- a/mapstruct-plus-processor/src/main/resources/META-INF/services/org.mapstruct.ap.internal.processor.ModelElementProcessor +++ b/mapstruct-plus-processor/src/main/resources/META-INF/services/org.mapstruct.ap.internal.processor.ModelElementProcessor @@ -11,5 +11,5 @@ org.mapstruct.ap.internal.processor.MapperRenderingProcessor org.mapstruct.ap.internal.processor.MethodRetrievalProcessor org.mapstruct.ap.internal.processor.SpringComponentProcessor org.mapstruct.ap.internal.processor.MapperServiceProcessor -io.github.linpeilie.processor.solon.SolonComponentProcessor +io.github.linpeilie.processor.enhance.processor.SolonComponentProcessor io.github.linpeilie.processor.enhance.processor.SpringComponentProcessor -- Gitee From b12cd2b14a7cc9d79b84adf53a0b46a43c66e6b0 Mon Sep 17 00:00:00 2001 From: linpeilie Date: Wed, 26 Jun 2024 16:42:00 +0800 Subject: [PATCH 03/13] version ---> 1.4.3-SNAPSHOT --- example/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/example/pom.xml b/example/pom.xml index cb33ca7..ad45f6f 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -18,7 +18,7 @@ UTF-8 1.5.1.Final - 1.4.2 + 1.4.3-SNAPSHOT 1.18.22 5.8.26 32.1.3-jre diff --git a/pom.xml b/pom.xml index 37086e0..4b419fa 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ - 1.4.2 + 1.4.3-SNAPSHOT 8 8 UTF-8 -- Gitee From 9bfe62a0c24853a0bfd7ccdc6b45e560dbe7b0ae Mon Sep 17 00:00:00 2001 From: linpeilie Date: Wed, 26 Jun 2024 16:47:08 +0800 Subject: [PATCH 04/13] modified the approach to avoid circular dependencies. --- .../processor/AutoMapperProcessor.java | 1 + .../generator/AutoMapperGenerator.java | 111 ++++++++++++++++-- .../linpeilie/BaseCycleAvoidingMapper.java | 7 -- .../java/io/github/linpeilie/BaseMapper.java | 4 - 4 files changed, 100 insertions(+), 23 deletions(-) diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java index 9d7150b..08d9f95 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java @@ -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: diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/AutoMapperGenerator.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/AutoMapperGenerator.java index 19deb35..23b0db3 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/AutoMapperGenerator.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/AutoMapperGenerator.java @@ -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()) { + 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.isCycleAvoiding() + ? CollectionUtils.newArrayList(source, context) + : Collections.singletonList(source), metadata.getFieldMappingList(), targetClassName, - CONVERT_METHOD_NAME)); + 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 parameterSpecs, List 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 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(); } diff --git a/mapstruct-plus/src/main/java/io/github/linpeilie/BaseCycleAvoidingMapper.java b/mapstruct-plus/src/main/java/io/github/linpeilie/BaseCycleAvoidingMapper.java index 75ba1f6..48c7773 100644 --- a/mapstruct-plus/src/main/java/io/github/linpeilie/BaseCycleAvoidingMapper.java +++ b/mapstruct-plus/src/main/java/io/github/linpeilie/BaseCycleAvoidingMapper.java @@ -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 extends BaseMapper { - @DoIgnore T convert(S source, @Context CycleAvoidingMappingContext context); - @DoIgnore T convert(S source, @MappingTarget T target, @Context CycleAvoidingMappingContext context); - @DoIgnore default List convert(List sourceList, @Context CycleAvoidingMappingContext context) { return sourceList.stream() .map(item -> convert(item, context)) @@ -22,20 +18,17 @@ public interface BaseCycleAvoidingMapper extends BaseMapper { } @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 convert(List sourceList) { return convert(sourceList, new CycleAvoidingMappingContext()); } diff --git a/mapstruct-plus/src/main/java/io/github/linpeilie/BaseMapper.java b/mapstruct-plus/src/main/java/io/github/linpeilie/BaseMapper.java index a89fa3e..eec5536 100644 --- a/mapstruct-plus/src/main/java/io/github/linpeilie/BaseMapper.java +++ b/mapstruct-plus/src/main/java/io/github/linpeilie/BaseMapper.java @@ -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 { - @DoIgnore T convert(S source); - @DoIgnore T convert(S source, @MappingTarget T target); - @DoIgnore default List convert(List sourceList) { if (CollectionUtils.isEmpty(sourceList)) { return new ArrayList<>(); -- Gitee From a1fddcd1ea6a2a0e52c7a074d91a8c7b29610c9a Mon Sep 17 00:00:00 2001 From: linpeilie Date: Wed, 26 Jun 2024 16:53:01 +0800 Subject: [PATCH 05/13] add AdapterMapperGeneratorFactory --- .../AdapterMapperGeneratorFactory.java | 23 +++++++++++++++++++ .../processor/AutoMapperProcessor.java | 12 +--------- 2 files changed, 24 insertions(+), 11 deletions(-) create mode 100644 mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AdapterMapperGeneratorFactory.java diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AdapterMapperGeneratorFactory.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AdapterMapperGeneratorFactory.java new file mode 100644 index 0000000..30c4196 --- /dev/null +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AdapterMapperGeneratorFactory.java @@ -0,0 +1,23 @@ +package io.github.linpeilie.processor; + +import io.github.linpeilie.ComponentModelConstant; +import io.github.linpeilie.processor.generator.DefaultAdapterMapperGenerator; +import io.github.linpeilie.processor.generator.SolonAdapterMapperGenerator; +import io.github.linpeilie.processor.generator.SpringAdapterMapperGenerator; +import org.mapstruct.MappingConstants; + +public class AdapterMapperGeneratorFactory { + + public static AbstractAdapterMapperGenerator instance(String componentModel) { + switch (AutoMapperProperties.getComponentModel()) { + case MappingConstants.ComponentModel.SPRING: + case ContextConstants.ComponentModelConfig.springLazy: + return new SpringAdapterMapperGenerator(); + case ComponentModelConstant.SOLON: + return new SolonAdapterMapperGenerator(); + default: + return new DefaultAdapterMapperGenerator(); + } + } + +} diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java index 08d9f95..3ff75b5 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java @@ -178,17 +178,7 @@ public class AutoMapperProcessor extends AbstractProcessor { refreshProperties(annotations, roundEnv); // 根据配置生成适配类生成器 - switch (AutoMapperProperties.getComponentModel()) { - case MappingConstants.ComponentModel.SPRING: - case ContextConstants.ComponentModelConfig.springLazy: - this.adapterMapperGenerator = new SpringAdapterMapperGenerator(); - break; - case ComponentModelConstant.SOLON: - this.adapterMapperGenerator = new SolonAdapterMapperGenerator(); - break; - default: - this.adapterMapperGenerator = new DefaultAdapterMapperGenerator(); - } + this.adapterMapperGenerator = AdapterMapperGeneratorFactory.instance(AutoMapperProperties.getComponentModel()); // AutoMapMapper final TypeElement autoMapMapperAnnotation = -- Gitee From 067a27f4d279f32a3d9036d53ea968b1fca343b9 Mon Sep 17 00:00:00 2001 From: linpeilie Date: Wed, 26 Jun 2024 18:02:32 +0800 Subject: [PATCH 06/13] in the case of the same class in different packages, and a suffix to the mapper class name --- .../processor/AutoMapperProcessor.java | 17 +++++++++++++++-- .../generator/AutoMapperGenerator.java | 13 ------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java index 3ff75b5..b32349b 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java @@ -117,6 +117,8 @@ public class AutoMapperProcessor extends AbstractProcessor { private final Set mapperSet = new HashSet<>(); + private static final Map AUTO_MAPPER_INDEX = new HashMap<>(); + private Messager messager; public AutoMapperProcessor() { @@ -517,10 +519,21 @@ public class AutoMapperProcessor extends AbstractProcessor { mapperList.addAll(reverseMapperMetadataList); + mapperList.removeIf(metadata -> !metadata.isConvertGenerate()); + + // 兼容同模块下,同名不同包的场景 mapperList.forEach(metadata -> { - if (!metadata.isConvertGenerate()) { - return; + String mapperName = metadata.mapperName(); + // 同名类时,增加后缀 + Integer index = AUTO_MAPPER_INDEX.getOrDefault(mapperName, 0); + if (index > 0) { + mapperName = mapperName + "__" + index; } + AUTO_MAPPER_INDEX.put(metadata.mapperName(), ++index); + metadata.setMapperName(mapperName); + }); + + mapperList.forEach(metadata -> { this.writeAutoMapperClassFile(metadata); addAdapterMethod(metadata); }); diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/AutoMapperGenerator.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/AutoMapperGenerator.java index 23b0db3..f53bb48 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/AutoMapperGenerator.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/AutoMapperGenerator.java @@ -32,22 +32,9 @@ public class AutoMapperGenerator { public static final String CONVERT_METHOD_NAME = "convert"; - private static final Map AUTO_MAPPER_INDEX = new HashMap<>(); - public void write(AutoMapperMetadata metadata, ProcessingEnvironment processingEnv) { String mapperPackage = metadata.mapperPackage(); - - /* - 当前处理方式,本地使用 IDEA 开发时,当修改 Source/Target 类时,可能还会出现类名冲突的问题, - 当出现该问题时,需要执行 clean 把之前构建的类清掉。 - */ String mapperName = metadata.mapperName(); - // 同名类时,增加后缀 - Integer index = AUTO_MAPPER_INDEX.getOrDefault(mapperName, 0); - if (index > 0) { - mapperName = mapperName + "__" + index; - } - AUTO_MAPPER_INDEX.put(metadata.mapperName(), ++index); try (final Writer writer = processingEnv.getFiler() .createSourceFile(mapperPackage + "." + mapperName) -- Gitee From 6bc4a6c16b077328cbb1debad4980c42156a8cbb Mon Sep 17 00:00:00 2001 From: linpeilie Date: Thu, 27 Jun 2024 15:09:23 +0800 Subject: [PATCH 07/13] in the case of the same class in different packages, and a suffix to the mapper class name --- .../AbstractAdapterMapperGenerator.java | 8 +- .../processor/AutoMapperProcessor.java | 100 ++++++++++++++++-- .../generator/IocAdapterMapperGenerator.java | 5 +- .../metadata/AutoMapperMetadata.java | 12 +++ 4 files changed, 113 insertions(+), 12 deletions(-) diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AbstractAdapterMapperGenerator.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AbstractAdapterMapperGenerator.java index c3e9e4a..426b5c3 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AbstractAdapterMapperGenerator.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AbstractAdapterMapperGenerator.java @@ -12,6 +12,7 @@ import io.github.linpeilie.processor.metadata.AbstractAdapterMethodMetadata; import io.github.linpeilie.processor.metadata.AdapterMapMethodMetadata; import io.github.linpeilie.processor.metadata.AdapterMethodMetadata; import io.github.linpeilie.utils.ClassUtil; +import io.github.linpeilie.utils.CollectionUtils; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; @@ -61,9 +62,6 @@ public abstract class AbstractAdapterMapperGenerator { .map(method -> buildProxyMethod(method, cycleAvoiding)) .flatMap(Collection::stream) .collect(Collectors.toList()); - if (methods.isEmpty()) { - return null; - } return createTypeSpec(methods, adapterClassName, cycleAvoiding ? ClassName.get(adapterPackage(), AutoMapperProperties.getAdapterClassName()) : null); } @@ -77,7 +75,9 @@ public abstract class AbstractAdapterMapperGenerator { } // adapter methods - adapterBuilder.addMethods(methods); + if (CollectionUtils.isNotEmpty(methods)) { + adapterBuilder.addMethods(methods); + } return adapterBuilder.build(); } diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java index b32349b..29ee1c0 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java @@ -1,6 +1,8 @@ package io.github.linpeilie.processor; +import com.squareup.javapoet.ArrayTypeName; import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; import io.github.linpeilie.ComponentModelConstant; import io.github.linpeilie.annotations.AutoEnumMapper; @@ -119,6 +121,8 @@ public class AutoMapperProcessor extends AbstractProcessor { private static final Map AUTO_MAPPER_INDEX = new HashMap<>(); + private final Map> typeRelationMappers = new HashMap<>(); + private Messager messager; public AutoMapperProcessor() { @@ -500,7 +504,7 @@ public class AutoMapperProcessor extends AbstractProcessor { mapperList.addAll(autoMapperMetadata); } - private void generateMapper() { + private List generateReverseConverters() { List reverseMapperMetadataList = new ArrayList<>(); mapperList.forEach(autoMapperMetadata -> { @@ -517,7 +521,25 @@ public class AutoMapperProcessor extends AbstractProcessor { reverseMapperMetadataList.add(reverseMapperMetadata); }); - mapperList.addAll(reverseMapperMetadataList); + return reverseMapperMetadataList; + } + + private void typeRelationMapper(AutoMapperMetadata metadata) { + String source = metadata.getSourceClassName().reflectionName(); + if (!typeRelationMappers.containsKey(source)) { + typeRelationMappers.put(source, new ArrayList<>()); + } + typeRelationMappers.get(source).add(metadata.mapperClass()); + + String target = metadata.getTargetClassName().reflectionName(); + if (!typeRelationMappers.containsKey(target)) { + typeRelationMappers.put(target, new ArrayList<>()); + } + typeRelationMappers.get(target).add(metadata.mapperClass()); + } + + private void generateMapper() { + mapperList.addAll(generateReverseConverters()); mapperList.removeIf(metadata -> !metadata.isConvertGenerate()); @@ -534,13 +556,30 @@ public class AutoMapperProcessor extends AbstractProcessor { }); mapperList.forEach(metadata -> { - this.writeAutoMapperClassFile(metadata); - addAdapterMethod(metadata); + if (metadata.isCycleAvoiding()) { + addAdapterMethod(metadata); + } else { + typeRelationMapper(metadata); + } }); - if (methodMap.isEmpty()) { - return; - } + // import dependency + mapperList.forEach(metadata -> { + Set dependencies = metadata.getDependencies(); + if (CollectionUtils.isNotEmpty(dependencies)) { + List dependencyMappers = dependencies.stream().map(dependency -> + typeRelationMappers.get(dependency.toString()) + ).filter(Objects::nonNull).flatMap(Collection::stream).collect(Collectors.toList()); + + if (CollectionUtils.isNotEmpty(dependencyMappers)) { + List uses = Optional.ofNullable(metadata.getUsesClassNameList()).orElse(new ArrayList<>()); + uses.addAll(dependencyMappers); + metadata.setUsesClassNameList(uses); + } + } + }); + + mapperList.forEach(this::writeAutoMapperClassFile); adapterMapperGenerator.write(processingEnv, methodMap.values(), @@ -567,6 +606,49 @@ public class AutoMapperProcessor extends AbstractProcessor { } } + private Set listDependencies(TypeElement autoMapperEle) { + Set set = new HashSet<>(); + + if (!autoMapperEle.getKind().isClass() && !autoMapperEle.getKind().isInterface()) { + return set; + } + + for (Element ele : autoMapperEle.getEnclosedElements()) { + if (ele.getKind() != ElementKind.FIELD) { + continue; + } + TypeName typeName = ClassName.get(ele.asType()); + if (typeName instanceof ArrayTypeName) { + ArrayTypeName arrayTypeName = (ArrayTypeName) typeName; + typeName = arrayTypeName.componentType; + } else if (typeName instanceof ParameterizedTypeName) { + ParameterizedTypeName parameterizedTypeName = (ParameterizedTypeName) typeName; + List typeArguments = parameterizedTypeName.typeArguments; + set.addAll(typeArguments); + continue; + } + set.add(typeName); + } + + // add super class dependencies + getSuperClass(autoMapperEle).ifPresent(superClass -> set.addAll(listDependencies(superClass))); + + set.removeIf(ele -> { + if (ele == null) { + return true; + } + try { + if (ele.box().isBoxedPrimitive()) { + return true; + } + } catch (Exception e) { + // ignore + } + return false; + }); + return set; + } + private AutoMapperMetadata reverseMapper(AutoMapperMetadata autoMapperMetadata) { AutoMapperMetadata reverseMapperMetadata = initAutoMapperMetadata(autoMapperMetadata.getTargetClassName(), @@ -765,6 +847,9 @@ public class AutoMapperProcessor extends AbstractProcessor { MapperUtils.getEnumMapperClassName(enumClass.simpleName()))) .collect(Collectors.toList()); + // dependencies + Set dependencies = listDependencies((TypeElement) ele); + usesClassNameList.addAll(useEnumClassNameList); metadata.setUsesClassNameList(usesClassNameList); @@ -794,6 +879,7 @@ public class AutoMapperProcessor extends AbstractProcessor { metadata.setMapperName(autoMapperGem.mapperName().getValue()); } metadata.setMapperNameSuffix(autoMapperGem.mapperNameSuffix().getValue()); + metadata.setDependencies(dependencies); addMapper(metadata, true); diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/IocAdapterMapperGenerator.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/IocAdapterMapperGenerator.java index e6d4930..540edbd 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/IocAdapterMapperGenerator.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/IocAdapterMapperGenerator.java @@ -8,6 +8,7 @@ import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.TypeSpec; import io.github.linpeilie.processor.AbstractAdapterMapperGenerator; import io.github.linpeilie.processor.metadata.AbstractAdapterMethodMetadata; +import io.github.linpeilie.utils.CollectionUtils; import java.util.List; import javax.lang.model.element.Modifier; @@ -27,7 +28,9 @@ public abstract class IocAdapterMapperGenerator extends AbstractAdapterMapperGen adapterBuilder.addField(buildConverterField()); - adapterBuilder.addMethods(methods); + if (CollectionUtils.isNotEmpty(methods)) { + adapterBuilder.addMethods(methods); + } if (superClass != null) { adapterBuilder.superclass(superClass); diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMapperMetadata.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMapperMetadata.java index 34c6532..d268874 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMapperMetadata.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMapperMetadata.java @@ -1,9 +1,11 @@ package io.github.linpeilie.processor.metadata; import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.TypeName; import io.github.linpeilie.processor.utils.MapperUtils; import io.github.linpeilie.utils.StrUtil; import java.util.List; +import java.util.Set; import org.mapstruct.NullValueMappingStrategy; import org.mapstruct.SubclassExhaustiveStrategy; @@ -65,6 +67,8 @@ public class AutoMapperMetadata extends AbstractMapperMetadata { private ClassName mappingControl; + private Set dependencies; + public String qualifiedMapperName() { return mapperPackage() + "." + mapperName(); } @@ -277,4 +281,12 @@ public class AutoMapperMetadata extends AbstractMapperMetadata { public void setMappingControl(ClassName mappingControl) { this.mappingControl = mappingControl; } + + public Set getDependencies() { + return dependencies; + } + + public void setDependencies(Set dependencies) { + this.dependencies = dependencies; + } } -- Gitee From b1aacc7a2d75c0cb7f411f1088f48a42eae089cb Mon Sep 17 00:00:00 2001 From: linpeilie Date: Fri, 28 Jun 2024 19:12:43 +0800 Subject: [PATCH 08/13] =?UTF-8?q?-=20=E4=BC=98=E5=8C=96=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E6=B3=A8=E5=85=A5=20-=20=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../processor/AutoMapperProcessor.java | 13 ++++- .../metadata/AutoMapperMetadata.java | 12 ++-- .../SpringDelayInjectMapperReference.ftl | 2 +- .../mapstruct/SpringContextUtils.java | 56 +++++++++++++++++-- 4 files changed, 71 insertions(+), 12 deletions(-) diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java index 29ee1c0..075c5aa 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java @@ -572,11 +572,18 @@ public class AutoMapperProcessor extends AbstractProcessor { ).filter(Objects::nonNull).flatMap(Collection::stream).collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(dependencyMappers)) { - List uses = Optional.ofNullable(metadata.getUsesClassNameList()).orElse(new ArrayList<>()); - uses.addAll(dependencyMappers); - metadata.setUsesClassNameList(uses); + metadata.addUseList(dependencyMappers); } } + // source + List sourceDependencies = + typeRelationMappers.get(metadata.getSourceClassName().reflectionName()); + + if (CollectionUtils.isNotEmpty(sourceDependencies)) { + sourceDependencies.removeIf( + sourceDependency -> sourceDependency.reflectionName().equals(metadata.mapperName())); + metadata.addUseList(sourceDependencies); + } }); mapperList.forEach(this::writeAutoMapperClassFile); diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMapperMetadata.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMapperMetadata.java index d268874..e8b248e 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMapperMetadata.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/metadata/AutoMapperMetadata.java @@ -4,6 +4,7 @@ import com.squareup.javapoet.ClassName; import com.squareup.javapoet.TypeName; import io.github.linpeilie.processor.utils.MapperUtils; import io.github.linpeilie.utils.StrUtil; +import java.util.ArrayList; import java.util.List; import java.util.Set; import org.mapstruct.NullValueMappingStrategy; @@ -73,6 +74,13 @@ public class AutoMapperMetadata extends AbstractMapperMetadata { return mapperPackage() + "." + mapperName(); } + public boolean addUseList(List uses) { + if (this.usesClassNameList == null) { + this.usesClassNameList = new ArrayList<>(); + } + return usesClassNameList.addAll(uses); + } + /*************** getter/setter ***************/ public String mapperName() { @@ -83,10 +91,6 @@ public class AutoMapperMetadata extends AbstractMapperMetadata { this.mapperName = mapperName; } - public String getMapperName() { - return mapperName; - } - public String getMapperNameSuffix() { return mapperNameSuffix; } diff --git a/mapstruct-plus-processor/src/main/resources/io/github/linpeilie/processor/enhance/model/SpringDelayInjectMapperReference.ftl b/mapstruct-plus-processor/src/main/resources/io/github/linpeilie/processor/enhance/model/SpringDelayInjectMapperReference.ftl index 894e219..f84aa7d 100644 --- a/mapstruct-plus-processor/src/main/resources/io/github/linpeilie/processor/enhance/model/SpringDelayInjectMapperReference.ftl +++ b/mapstruct-plus-processor/src/main/resources/io/github/linpeilie/processor/enhance/model/SpringDelayInjectMapperReference.ftl @@ -1,2 +1,2 @@ <#-- @ftlvariable name="" type="io.github.linpeilie.processor.enhance.model.SpringDelayInjectMapperReference" --> -private <@includeModel object=type/> ${variableName} = SpringContextUtils.getBean(<@includeModel object=type/>.class); \ No newline at end of file +private <@includeModel object=type/> ${variableName} = SpringContextUtils.getBean("${variableName}", <@includeModel object=type/>.class); \ No newline at end of file diff --git a/mapstruct-plus-spring-boot-starter/src/main/java/io/github/linpeilie/mapstruct/SpringContextUtils.java b/mapstruct-plus-spring-boot-starter/src/main/java/io/github/linpeilie/mapstruct/SpringContextUtils.java index b34275f..bdb201a 100644 --- a/mapstruct-plus-spring-boot-starter/src/main/java/io/github/linpeilie/mapstruct/SpringContextUtils.java +++ b/mapstruct-plus-spring-boot-starter/src/main/java/io/github/linpeilie/mapstruct/SpringContextUtils.java @@ -1,20 +1,68 @@ package io.github.linpeilie.mapstruct; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.beans.factory.NoUniqueBeanDefinitionException; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ConfigurableApplicationContext; -public class SpringContextUtils implements ApplicationContextAware { +public class SpringContextUtils implements BeanFactoryPostProcessor, ApplicationContextAware { + private static ConfigurableListableBeanFactory beanFactory; private static ApplicationContext applicationContext; - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + public SpringContextUtils() { + } + + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + SpringContextUtils.beanFactory = beanFactory; + } + + public void setApplicationContext(ApplicationContext applicationContext) { SpringContextUtils.applicationContext = applicationContext; } + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + public static ListableBeanFactory getBeanFactory() { + ListableBeanFactory factory = null == beanFactory ? applicationContext : beanFactory; + if (null == factory) { + throw new RuntimeException("No ConfigurableListableBeanFactory or ApplicationContext injected, maybe not in the Spring environment?"); + } else { + return (ListableBeanFactory)factory; + } + } + + public static ConfigurableListableBeanFactory getConfigurableBeanFactory() { + ConfigurableListableBeanFactory factory; + if (null != beanFactory) { + factory = beanFactory; + } else { + if (!(applicationContext instanceof ConfigurableApplicationContext)) { + throw new RuntimeException("No ConfigurableListableBeanFactory from context!"); + } + + factory = ((ConfigurableApplicationContext)applicationContext).getBeanFactory(); + } + + return factory; + } + public static T getBean(Class clazz) { - return applicationContext.getBean(clazz); + return getBeanFactory().getBean(clazz); + } + + public static T getBean(String name, Class clazz) { + try { + return getBean(clazz); + } catch (NoUniqueBeanDefinitionException e) { + return getBeanFactory().getBean(name, clazz); + } } } -- Gitee From 8d7246b2075e8dcbd6eedfac3d1d8ee4a49b4fc6 Mon Sep 17 00:00:00 2001 From: linpeilie Date: Fri, 28 Jun 2024 19:54:00 +0800 Subject: [PATCH 09/13] =?UTF-8?q?=E4=BF=AE=E6=94=B9unmappedTargetPolicy?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/github/linpeilie/processor/AutoMapperProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java index 075c5aa..9713c44 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java @@ -378,7 +378,7 @@ public class AutoMapperProcessor extends AbstractProcessor { } AutoMapperProperties.setUnmappedSourcePolicy(mapperConfigGem.unmappedSourcePolicy().getValue()); // 重定义 MapStruct 中 unmappedTargetPolicy 的默认值 WARN ---> IGNORE - AutoMapperProperties.setUnmappedTargetPolicy(mapperConfigGem.unmappedTargetPolicy().getValue()); + AutoMapperProperties.setUnmappedTargetPolicy(mapperConfigGem.unmappedTargetPolicy().get()); AutoMapperProperties.setTypeConversionPolicy(mapperConfigGem.typeConversionPolicy().getValue()); AutoMapperProperties.setCollectionMappingStrategy(mapperConfigGem.collectionMappingStrategy().getValue()); AutoMapperProperties.setNullValueMappingStrategy(mapperConfigGem.nullValueMappingStrategy().getValue()); -- Gitee From 53b16f0c57d5ef742e569d2d5b91f8625752706e Mon Sep 17 00:00:00 2001 From: linpeilie Date: Fri, 28 Jun 2024 21:10:56 +0800 Subject: [PATCH 10/13] uses remove itself --- .../io/github/linpeilie/processor/AutoMapperProcessor.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java index 9713c44..e8c1484 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java @@ -580,10 +580,13 @@ public class AutoMapperProcessor extends AbstractProcessor { typeRelationMappers.get(metadata.getSourceClassName().reflectionName()); if (CollectionUtils.isNotEmpty(sourceDependencies)) { - sourceDependencies.removeIf( - sourceDependency -> sourceDependency.reflectionName().equals(metadata.mapperName())); metadata.addUseList(sourceDependencies); } + // remove itself + if (CollectionUtils.isNotEmpty(metadata.getUsesClassNameList())) { + metadata.getUsesClassNameList() + .removeIf(use -> use.reflectionName().equals(metadata.mapperClass().reflectionName())); + } }); mapperList.forEach(this::writeAutoMapperClassFile); -- Gitee From f4246d8248e7129a4f530626cd36bd042aeb8433 Mon Sep 17 00:00:00 2001 From: linpeilie Date: Fri, 28 Jun 2024 21:11:05 +0800 Subject: [PATCH 11/13] =?UTF-8?q?=E4=BF=AE=E6=94=B9unmappedTargetPolicy?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/github/linpeilie/processor/AutoMapperProperties.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProperties.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProperties.java index ddb68fe..65e0804 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProperties.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProperties.java @@ -15,7 +15,7 @@ public class AutoMapperProperties { private static String unmappedSourcePolicy; - private static String unmappedTargetPolicy; + private static String unmappedTargetPolicy = "IGNORE"; private static String typeConversionPolicy; -- Gitee From c926e9ba707cd6be98eba8012829a83692269ed0 Mon Sep 17 00:00:00 2001 From: linpeilie Date: Sat, 29 Jun 2024 10:45:51 +0800 Subject: [PATCH 12/13] =?UTF-8?q?=E5=87=8F=E5=B0=91=E5=BE=AA=E7=8E=AF?= =?UTF-8?q?=E6=AC=A1=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../processor/AutoMapperProcessor.java | 80 ++++++++++--------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java index e8c1484..a5d4c15 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/AutoMapperProcessor.java @@ -543,19 +543,10 @@ public class AutoMapperProcessor extends AbstractProcessor { mapperList.removeIf(metadata -> !metadata.isConvertGenerate()); - // 兼容同模块下,同名不同包的场景 mapperList.forEach(metadata -> { - String mapperName = metadata.mapperName(); - // 同名类时,增加后缀 - Integer index = AUTO_MAPPER_INDEX.getOrDefault(mapperName, 0); - if (index > 0) { - mapperName = mapperName + "__" + index; - } - AUTO_MAPPER_INDEX.put(metadata.mapperName(), ++index); - metadata.setMapperName(mapperName); - }); + // 兼容同模块下,同名不同包的场景 + this.mapperNameAddSuffix(metadata); - mapperList.forEach(metadata -> { if (metadata.isCycleAvoiding()) { addAdapterMethod(metadata); } else { @@ -563,34 +554,12 @@ public class AutoMapperProcessor extends AbstractProcessor { } }); - // import dependency mapperList.forEach(metadata -> { - Set dependencies = metadata.getDependencies(); - if (CollectionUtils.isNotEmpty(dependencies)) { - List dependencyMappers = dependencies.stream().map(dependency -> - typeRelationMappers.get(dependency.toString()) - ).filter(Objects::nonNull).flatMap(Collection::stream).collect(Collectors.toList()); - - if (CollectionUtils.isNotEmpty(dependencyMappers)) { - metadata.addUseList(dependencyMappers); - } - } - // source - List sourceDependencies = - typeRelationMappers.get(metadata.getSourceClassName().reflectionName()); - - if (CollectionUtils.isNotEmpty(sourceDependencies)) { - metadata.addUseList(sourceDependencies); - } - // remove itself - if (CollectionUtils.isNotEmpty(metadata.getUsesClassNameList())) { - metadata.getUsesClassNameList() - .removeIf(use -> use.reflectionName().equals(metadata.mapperClass().reflectionName())); - } + this.relationDependencies(metadata); + this.usesRemoveItself(metadata); + this.writeAutoMapperClassFile(metadata); }); - mapperList.forEach(this::writeAutoMapperClassFile); - adapterMapperGenerator.write(processingEnv, methodMap.values(), AutoMapperProperties.getAdapterClassName(), @@ -616,6 +585,45 @@ public class AutoMapperProcessor extends AbstractProcessor { } } + private void mapperNameAddSuffix(AutoMapperMetadata metadata) { + String mapperName = metadata.mapperName(); + // 同名类时,增加后缀 + Integer index = AUTO_MAPPER_INDEX.getOrDefault(mapperName, 0); + if (index > 0) { + mapperName = mapperName + "__" + index; + } + AUTO_MAPPER_INDEX.put(metadata.mapperName(), ++index); + metadata.setMapperName(mapperName); + } + + private void relationDependencies(AutoMapperMetadata metadata) { + Set dependencies = metadata.getDependencies(); + if (CollectionUtils.isNotEmpty(dependencies)) { + List dependencyMappers = dependencies.stream().map(dependency -> + typeRelationMappers.get(dependency.toString()) + ).filter(Objects::nonNull).flatMap(Collection::stream).collect(Collectors.toList()); + + if (CollectionUtils.isNotEmpty(dependencyMappers)) { + metadata.addUseList(dependencyMappers); + } + } + // source + List sourceDependencies = + typeRelationMappers.get(metadata.getSourceClassName().reflectionName()); + + if (CollectionUtils.isNotEmpty(sourceDependencies)) { + metadata.addUseList(sourceDependencies); + } + } + + private void usesRemoveItself(AutoMapperMetadata metadata) { + // remove itself + if (CollectionUtils.isNotEmpty(metadata.getUsesClassNameList())) { + metadata.getUsesClassNameList() + .removeIf(use -> use.reflectionName().equals(metadata.mapperClass().reflectionName())); + } + } + private Set listDependencies(TypeElement autoMapperEle) { Set set = new HashSet<>(); -- Gitee From 5d9154487812fd29b75b3dc652429a8e9fd5b601 Mon Sep 17 00:00:00 2001 From: linpeilie Date: Sat, 29 Jun 2024 13:55:34 +0800 Subject: [PATCH 13/13] release 1.4.3 --- README.md | 2 +- docs/README.md | 17 ++++++++--------- docs/en/README.md | 14 +++++++------- docs/en/release/log.md | 6 ++++++ docs/release/log.md | 6 ++++++ example/pom.xml | 2 +- .../annotations/ComponentModelConfig.java | 2 +- pom.xml | 2 +- 8 files changed, 31 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 91cf813..110479a 100644 --- a/README.md +++ b/README.md @@ -188,7 +188,7 @@ public class User { ```xml - 1.4.2 + 1.4.3 diff --git a/docs/README.md b/docs/README.md index aa779a7..8ebe737 100644 --- a/docs/README.md +++ b/docs/README.md @@ -62,18 +62,24 @@ footer: io.github.linpeilie mapstruct-plus-spring-boot-starter - 1.4.2 + 1.4.3 ``` - gradle ```groovy -implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-starter', version: '1.4.2' +implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-starter', version: '1.4.3' ``` ## 更新日志 +### 1.4.3 + +- feat: `ComponentModel` 增加 `spring-lazy` 可选项,懒加载 Spring Bean,解决互相依赖的问题,并将默认配置改为该选项; +- fix: 解决 `unmappedTargetPolicy` 默认配置不生效的问题; +- enhance: 优化 IDEA 本地开发构建效率,一定程度上缩短构建时间、减小元空间占用;[Issue #89](https://github.com/linpeilie/mapstruct-plus/issues/89) + ### 1.4.2 - feat: `AutoMapper` 注解增加 `mapperNameSuffix` 属性,支持配置生成的转换接口名称增加后缀,默认规则下生成的反向转换接口同时生效; @@ -101,13 +107,6 @@ implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-s > 当然,这个问题在之前也会有,几率可能低一些,所以多模块下,务必配置 `adapterPackage` 来避免该问题。 > - Map 与对象的转换,还是依赖 hutool 中的类转换实现,如果需要该功能,需要额外引入 `hutool-core` 依赖包。 -### 1.3.6 - -- 兼容内部类转换 -- feature : AutoMapping 注解中的 targetClass 支持配置父类 -- [issue#I8QPRO](https://gitee.com/easii/mapstruct-plus/issues/I8QPRO) : 框架自动生成的 AutoMapperConfig 和 AutoMapMapper 包和类名支持配置 -- [issue#I8T7EF](https://gitee.com/easii/mapstruct-plus/issues/I8T7EF) : 支持在父类中配置的 AutoMapping 注解 - …… ## 代码仓库 diff --git a/docs/en/README.md b/docs/en/README.md index 14cc8fe..5bfff1a 100644 --- a/docs/en/README.md +++ b/docs/en/README.md @@ -58,25 +58,25 @@ fotter: io.github.linpeilie mapstruct-plus-spring-boot-starter - 1.4.0 + 1.4.3 ``` - gradle ```groovy -implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-starter', version: '1.4.0' +implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-starter', version: '1.4.3' ``` ## Change Log -### 1.4.2 - -Sure, here is the translated update document: +### 1.4.3 ---- +- **feat**: Added `spring-lazy` option to `ComponentModel` for lazy loading Spring Beans, resolving mutual dependency issues, and set this option as the default configuration. +- **fix**: Fixed the issue where the default configuration for `unmappedTargetPolicy` was not effective. +- **enhance**: Optimized IDEA local development build efficiency, reducing build time and metaspace usage to some extent.[Issue #89](https://github.com/linpeilie/mapstruct-plus/issues/89) -### Updates +### 1.4.2 - **feat**: Added the `mapperNameSuffix` attribute to the `AutoMapper` annotation. This supports adding a suffix to the generated conversion interface name, and the reverse conversion interface will be effective under the default rules. - **feat**: Adapted the `Mapper` annotation to support the following attributes: `unmappedSourcePolicy`, `unmappedTargetPolicy`, `typeConversionPolicy`, `collectionMappingStrategy`, `nullValueMappingStrategy`, `nullValueIterableMappingStrategy`, `nullValuePropertyMappingStrategy`, `nullValueCheckStrategy`, and `mappingControl`. diff --git a/docs/en/release/log.md b/docs/en/release/log.md index 4e16820..e529437 100644 --- a/docs/en/release/log.md +++ b/docs/en/release/log.md @@ -6,6 +6,12 @@ category: description: MapStructPlus release log --- +### 1.4.3 + +- **feat**: Added `spring-lazy` option to `ComponentModel` for lazy loading Spring Beans, resolving mutual dependency issues, and set this option as the default configuration. +- **fix**: Fixed the issue where the default configuration for `unmappedTargetPolicy` was not effective. +- **enhance**: Optimized IDEA local development build efficiency, reducing build time and metaspace usage to some extent.[Issue #89](https://github.com/linpeilie/mapstruct-plus/issues/89) + ### 1.4.2 - **feat**: Added the `mapperNameSuffix` attribute to the `AutoMapper` annotation. This supports adding a suffix to the generated conversion interface name, and the reverse conversion interface will be effective under the default rules. diff --git a/docs/release/log.md b/docs/release/log.md index f69f9f0..2d5c40f 100644 --- a/docs/release/log.md +++ b/docs/release/log.md @@ -6,6 +6,12 @@ category: description: MapStructPlus release log --- +### 1.4.3 + +- feat: `ComponentModel` 增加 `spring-lazy` 可选项,懒加载 Spring Bean,解决互相依赖的问题,并将默认配置改为该选项; +- fix: 解决 `unmappedTargetPolicy` 默认配置不生效的问题; +- enhance: 优化 IDEA 本地开发构建效率,一定程度上缩短构建时间、减小元空间占用;[Issue #89](https://github.com/linpeilie/mapstruct-plus/issues/89) + ### 1.4.2 - feat: `AutoMapper` 注解增加 `mapperNameSuffix` 属性,支持配置生成的转换接口名称增加后缀,默认规则下生成的反向转换接口同时生效; diff --git a/example/pom.xml b/example/pom.xml index ad45f6f..d5d2a39 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -18,7 +18,7 @@ UTF-8 1.5.1.Final - 1.4.3-SNAPSHOT + 1.4.3 1.18.22 5.8.26 32.1.3-jre diff --git a/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/ComponentModelConfig.java b/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/ComponentModelConfig.java index d63c97c..4e64a3e 100644 --- a/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/ComponentModelConfig.java +++ b/mapstruct-plus/src/main/java/io/github/linpeilie/annotations/ComponentModelConfig.java @@ -9,6 +9,6 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.SOURCE) public @interface ComponentModelConfig { - String componentModel() default "spring"; + String componentModel() default "spring-lazy"; } diff --git a/pom.xml b/pom.xml index 4b419fa..f155c12 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ - 1.4.3-SNAPSHOT + 1.4.3 8 8 UTF-8 -- Gitee