diff --git a/README.md b/README.md index 97e856a..fc8a05d 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ public class User { ```xml - 1.2.4 + 1.2.5 diff --git a/docs/README.md b/docs/README.md index 6115b01..1bb5ab9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -52,14 +52,14 @@ copyright: false io.github.linpeilie mapstruct-plus-spring-boot-starter - 1.2.4 + 1.2.5 ``` - gradle ```groovy -implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-starter', version: '1.2.4' +implementation group: 'io.github.linpeilie', name: 'mapstruct-plus-spring-boot-starter', version: '1.2.5' ``` ## 更新日志 diff --git a/example/pom.xml b/example/pom.xml index 7b5c8f1..fdc6f13 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -18,7 +18,7 @@ UTF-8 1.5.1.Final - 1.2.3 + 1.2.5 1.18.22 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 a4da458..7225497 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 @@ -1,9 +1,12 @@ package io.github.linpeilie.processor; +import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; 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.metadata.AbstractAdapterMethodMetadata; import java.io.IOException; @@ -39,11 +42,24 @@ public abstract class AbstractAdapterMapperGenerator { return AutoMapperProperties.getAdapterPackage(); } + private TypeName wrapperTypeName(TypeName source) { + if (source.isPrimitive() || source.isBoxedPrimitive()) { + return source; + } + if ("java.util.Map".contentEquals(source.toString())) { + return ParameterizedTypeName.get((ClassName) source, + ClassName.get("java.lang", "String"), + ClassName.get("java.lang", "Object")); + } + return source; + } + protected MethodSpec buildProxyMethod(AbstractAdapterMethodMetadata adapterMethodMetadata) { CodeBlock targetCode = adapterMethodMetadata.isStatic() ? CodeBlock.of("return $T.$N($N);", adapterMethodMetadata.getMapper(), adapterMethodMetadata.getMapperMethodName(), "param") : proxyMethodTarget(adapterMethodMetadata); - ParameterSpec parameterSpec = ParameterSpec.builder(adapterMethodMetadata.getSource(), "param").build(); + ParameterSpec parameterSpec = ParameterSpec.builder( + wrapperTypeName(adapterMethodMetadata.getSource()), "param").build(); return MethodSpec.methodBuilder(adapterMethodMetadata.getMethodName()) .addModifiers(Modifier.PUBLIC) .addParameter(parameterSpec) 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 1e334fa..1d07f15 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 @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.TypeName; +import io.github.linpeilie.ComponentModelConstant; import io.github.linpeilie.annotations.AutoEnumMapper; import io.github.linpeilie.annotations.AutoMapMapper; import io.github.linpeilie.annotations.AutoMapper; @@ -18,6 +19,7 @@ import io.github.linpeilie.processor.generator.AutoEnumMapperGenerator; import io.github.linpeilie.processor.generator.AutoMapperGenerator; import io.github.linpeilie.processor.generator.DefaultAdapterMapperGenerator; import io.github.linpeilie.processor.generator.MapperConfigGenerator; +import io.github.linpeilie.processor.generator.SolonAdapterMapperGenerator; import io.github.linpeilie.processor.generator.SpringAdapterMapperGenerator; import io.github.linpeilie.processor.metadata.AbstractAdapterMethodMetadata; import io.github.linpeilie.processor.metadata.AdapterEnumMethodMetadata; @@ -66,11 +68,13 @@ import static javax.tools.Diagnostic.Kind.ERROR; @SupportedAnnotationTypes({AUTO_MAPPER_ANNOTATION, AUTO_MAPPERS_ANNOTATION, AUTO_MAP_MAPPER_ANNOTATION, AUTO_ENUM_MAPPER_ANNOTATION, MAPPER_CONFIG_ANNOTATION, COMPONENT_MODEL_CONFIG_ANNOTATION, - MAPPER_ANNOTATION}) + MAPPER_ANNOTATION}) public class AutoMapperProcessor extends AbstractProcessor { private static final ClassName MAPPING_DEFAULT_TARGET = ClassName.get("io.github.linpeilie", "DefaultMapping"); + protected static final String DEFAULT_COMPONENT_MODEL = "mapstruct.defaultComponentModel"; + private final AutoMapperGenerator mapperGenerator; private AbstractAdapterMapperGenerator adapterMapperGenerator; @@ -133,9 +137,16 @@ public class AutoMapperProcessor extends AbstractProcessor { refreshProperties(annotations, roundEnv); // 根据配置生成适配类生成器 - this.adapterMapperGenerator = AutoMapperProperties.getComponentModel() - .contentEquals( - MappingConstants.ComponentModel.SPRING) ? new SpringAdapterMapperGenerator() : new DefaultAdapterMapperGenerator(); + switch (AutoMapperProperties.getComponentModel()) { + case MappingConstants.ComponentModel.SPRING: + this.adapterMapperGenerator = new SpringAdapterMapperGenerator(); + break; + case ComponentModelConstant.SOLON: + this.adapterMapperGenerator = new SolonAdapterMapperGenerator(); + break; + default: + this.adapterMapperGenerator = new DefaultAdapterMapperGenerator(); + } // AutoMapMapper annotations.stream() @@ -301,7 +312,8 @@ public class AutoMapperProcessor extends AbstractProcessor { AutoMapperProperties.setUnmappedSourcePolicy(mapperConfig.unmappedSourcePolicy()); AutoMapperProperties.setUnmappedTargetPolicy(mapperConfig.unmappedTargetPolicy()); AutoMapperProperties.setNullValueMappingStrategy(mapperConfig.nullValueMappingStrategy()); - AutoMapperProperties.setNullValuePropertyMappingStrategy(mapperConfig.nullValuePropertyMappingStrategy()); + AutoMapperProperties.setNullValuePropertyMappingStrategy( + mapperConfig.nullValuePropertyMappingStrategy()); AutoMapperProperties.setBuildMethod(mapperConfig.builder().buildMethod()); AutoMapperProperties.setDisableBuilder(mapperConfig.builder().disableBuilder()); if (StrUtil.isNotEmpty(mapperConfig.adapterPackage())) { @@ -314,16 +326,20 @@ public class AutoMapperProcessor extends AbstractProcessor { AutoMapperProperties.setMapAdapterClassName(mapperConfig.mapAdapterClassName()); } }); + // 构建参数 + String componentModel = processingEnv.getOptions().get(DEFAULT_COMPONENT_MODEL); + AutoMapperProperties.setComponentModel(componentModel); + annotations.stream() .filter(this::isComponentModelConfigAnnotation) .findFirst() .flatMap(annotation -> roundEnv.getElementsAnnotatedWith(annotation).stream().findFirst()) .ifPresent(element -> { - final ComponentModelConfig componentModelConfig = element.getAnnotation(ComponentModelConfig.class); - String componentModel = StringUtils.isEmpty( - componentModelConfig.componentModel()) ? "default" : componentModelConfig.componentModel(); - processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "component model " + componentModel); - AutoMapperProperties.setComponentModel(componentModel); + if (StrUtil.isEmpty(componentModel)) { + final ComponentModelConfig componentModelConfig = element.getAnnotation(ComponentModelConfig.class); + String componentModelByAnnotation = componentModelConfig.componentModel(); + AutoMapperProperties.setComponentModel(componentModelByAnnotation); + } }); } 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 new file mode 100644 index 0000000..0de2aad --- /dev/null +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/IocAdapterMapperGenerator.java @@ -0,0 +1,58 @@ +package io.github.linpeilie.processor.generator; + +import com.squareup.javapoet.AnnotationSpec; +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.TypeSpec; +import io.github.linpeilie.processor.AbstractAdapterMapperGenerator; +import io.github.linpeilie.processor.metadata.AbstractAdapterMethodMetadata; +import java.util.Collection; +import java.util.List; +import javax.lang.model.element.Modifier; + +public abstract class IocAdapterMapperGenerator extends AbstractAdapterMapperGenerator { + + protected abstract AnnotationSpec componentAnnotation(); + + protected abstract List injectAnnotations(); + + @Override + protected TypeSpec createTypeSpec(final Collection adapterMethods, + final String adapterClassName) { + TypeSpec.Builder adapterBuilder = TypeSpec.classBuilder(ClassName.get(adapterPackage(), adapterClassName)) + .addModifiers(Modifier.PUBLIC) + .addAnnotation(componentAnnotation()); + + adapterMethods.stream() + .filter(adapterMethodMetadata -> !adapterMethodMetadata.isStatic()) + .map(AbstractAdapterMethodMetadata::getMapper) + .distinct() + .forEach(mapper -> adapterBuilder.addField(buildMapperField(mapper))); + + adapterMethods.forEach(adapterMethod -> adapterBuilder + .addMethod(buildProxyMethod(adapterMethod))); + + return adapterBuilder.build(); + } + + private FieldSpec buildMapperField(ClassName mapper) { + return FieldSpec.builder(mapper, firstWordToLower(mapper.simpleName()), Modifier.PRIVATE) + .addAnnotations(injectAnnotations()) + .build(); + } + + private String firstWordToLower(String str) { + return str.substring(0, 1).toLowerCase() + str.substring(1); + } + + @Override + protected CodeBlock proxyMethodTarget(AbstractAdapterMethodMetadata adapterMethodMetadata) { + return CodeBlock.builder() + .add("return $N.$N($N);", firstWordToLower(adapterMethodMetadata.getMapper().simpleName()), + adapterMethodMetadata.getMapperMethodName(), + "param") + .build(); + } + +} diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/SolonAdapterMapperGenerator.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/SolonAdapterMapperGenerator.java new file mode 100644 index 0000000..87c4447 --- /dev/null +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/SolonAdapterMapperGenerator.java @@ -0,0 +1,30 @@ +package io.github.linpeilie.processor.generator; + +import cn.hutool.core.collection.CollectionUtil; +import com.squareup.javapoet.AnnotationSpec; +import com.squareup.javapoet.ClassName; +import java.util.Collection; +import java.util.List; + +public class SolonAdapterMapperGenerator extends IocAdapterMapperGenerator { + + private AnnotationSpec component() { + return AnnotationSpec.builder(ClassName.get("org.noear.solon.annotation", "Component")) + .build(); + } + + private AnnotationSpec inject() { + return AnnotationSpec.builder(ClassName.get("org.noear.solon.annotation", "Inject")) + .build(); + } + + @Override + protected AnnotationSpec componentAnnotation() { + return component(); + } + + @Override + protected List injectAnnotations() { + return CollectionUtil.newArrayList(inject()); + } +} diff --git a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/SpringAdapterMapperGenerator.java b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/SpringAdapterMapperGenerator.java index 3df93d5..2381d25 100644 --- a/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/SpringAdapterMapperGenerator.java +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/generator/SpringAdapterMapperGenerator.java @@ -1,5 +1,6 @@ package io.github.linpeilie.processor.generator; +import cn.hutool.core.collection.CollectionUtil; import com.squareup.javapoet.AnnotationSpec; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; @@ -10,63 +11,37 @@ import com.squareup.javapoet.TypeSpec; import io.github.linpeilie.processor.AbstractAdapterMapperGenerator; import io.github.linpeilie.processor.metadata.AbstractAdapterMethodMetadata; import java.util.Collection; +import java.util.List; import javax.lang.model.element.Modifier; -public class SpringAdapterMapperGenerator extends AbstractAdapterMapperGenerator { +public class SpringAdapterMapperGenerator extends IocAdapterMapperGenerator { - @Override - protected TypeSpec createTypeSpec(Collection adapterMethods, String adapterClassName) { - TypeSpec.Builder adapterBuilder = TypeSpec.classBuilder(ClassName.get(adapterPackage(), adapterClassName)) - .addModifiers(Modifier.PUBLIC) - .addAnnotation(ClassName.get("org.springframework.stereotype", "Component")); - - adapterMethods.stream() - .filter(adapterMethodMetadata -> !adapterMethodMetadata.isStatic()) - .map(AbstractAdapterMethodMetadata::getMapper) - .distinct() - .forEach(mapper -> adapterBuilder.addField(buildMapperField(mapper)) - .addMethod(buildMapperSetterMethod(mapper))); - - adapterMethods.forEach(adapterMethod -> adapterBuilder - .addMethod(buildProxyMethod(adapterMethod))); - - return adapterBuilder.build(); + private AnnotationSpec component() { + return AnnotationSpec + .builder(ClassName.get("org.springframework.stereotype", "Component")) + .build(); } - private FieldSpec buildMapperField(ClassName mapper) { - return FieldSpec.builder(mapper, firstWordToLower(mapper.simpleName()), Modifier.PRIVATE).build(); + private AnnotationSpec autowired() { + return AnnotationSpec + .builder(ClassName.get("org.springframework.beans", "Autowired")) + .build(); } - private String firstWordToLower(String str) { - return str.substring(0, 1).toLowerCase() + str.substring(1); + private AnnotationSpec lazy() { + return AnnotationSpec + .builder(ClassName.get("org.springframework.context.annotation", "Lazy")) + .build(); } @Override - protected CodeBlock proxyMethodTarget(AbstractAdapterMethodMetadata adapterMethodMetadata) { - return CodeBlock.builder() - .add("return $N.$N($N);", firstWordToLower(adapterMethodMetadata.getMapper().simpleName()), - adapterMethodMetadata.getMapperMethodName(), - "param") - .build(); + protected AnnotationSpec componentAnnotation() { + return component(); } - private MethodSpec buildMapperSetterMethod(ClassName mapper) { - ParameterSpec parameterSpec = buildMapperSetterParameter(mapper); - return MethodSpec.methodBuilder("set" + mapper.simpleName()) - .addModifiers(Modifier.PUBLIC) - .addParameter(parameterSpec) - .addAnnotation( - AnnotationSpec.builder(ClassName.get("org.springframework.beans.factory.annotation", "Autowired")) - .build()) - .addStatement("this.$N = $N", buildMapperField(mapper), parameterSpec) - .build(); - } - - private ParameterSpec buildMapperSetterParameter(ClassName mapper) { - return ParameterSpec.builder(mapper, firstWordToLower(mapper.simpleName())) - .addAnnotation( - AnnotationSpec.builder(ClassName.get("org.springframework.context.annotation", "Lazy")).build()) - .build(); + @Override + protected List injectAnnotations() { + return CollectionUtil.newArrayList(autowired(), lazy()); } } 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/solon/SolonComponentProcessor.java new file mode 100644 index 0000000..168668d --- /dev/null +++ b/mapstruct-plus-processor/src/main/java/io/github/linpeilie/processor/solon/SolonComponentProcessor.java @@ -0,0 +1,39 @@ +package io.github.linpeilie.processor.solon; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.collection.ListUtil; +import io.github.linpeilie.ComponentModelConstant; +import java.util.List; +import org.mapstruct.ap.internal.model.Annotation; +import org.mapstruct.ap.internal.model.Mapper; +import org.mapstruct.ap.internal.processor.AnnotationBasedComponentModelProcessor; + +public class SolonComponentProcessor extends AnnotationBasedComponentModelProcessor { + @Override + protected String getComponentModelIdentifier() { + return ComponentModelConstant.SOLON; + } + + @Override + protected List getTypeAnnotations(final Mapper mapper) { + return CollectionUtil.newArrayList(component()); + } + + private Annotation component() { + return new Annotation(getTypeFactory().getType("org.noear.solon.annotation.Component")); + } + + private Annotation inject() { + return new Annotation(getTypeFactory().getType("org.noear.solon.annotation.Inject")); + } + + @Override + protected List getMapperReferenceAnnotations() { + return CollectionUtil.newArrayList(inject()); + } + + @Override + protected boolean requiresGenerationOfDecoratorClass() { + return true; + } +} 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 new file mode 100644 index 0000000..a144912 --- /dev/null +++ b/mapstruct-plus-processor/src/main/resources/META-INF/services/org.mapstruct.ap.internal.processor.ModelElementProcessor @@ -0,0 +1,14 @@ +# Copyright MapStruct Authors. +# +# Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + +org.mapstruct.ap.internal.processor.CdiComponentProcessor +org.mapstruct.ap.internal.processor.JakartaCdiComponentProcessor +org.mapstruct.ap.internal.processor.Jsr330ComponentProcessor +org.mapstruct.ap.internal.processor.JakartaComponentProcessor +org.mapstruct.ap.internal.processor.MapperCreationProcessor +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 diff --git a/mapstruct-plus/src/main/java/io/github/linpeilie/ComponentModelConstant.java b/mapstruct-plus/src/main/java/io/github/linpeilie/ComponentModelConstant.java new file mode 100644 index 0000000..1565357 --- /dev/null +++ b/mapstruct-plus/src/main/java/io/github/linpeilie/ComponentModelConstant.java @@ -0,0 +1,7 @@ +package io.github.linpeilie; + +public interface ComponentModelConstant { + + String SOLON = "solon"; + +} diff --git a/pom.xml b/pom.xml index f57c5a5..40d647b 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ - 1.2.4 + 1.2.5 8 8 UTF-8