프로젝트에서 MapStruct 패키지 사용
6833 단어 javabean
인터넷에서 다른 사람이 테스트한 성능 대비를 해봤어요.
pc 구성: i7,16G 메모리 다양한 Bean 복사 도구 비교
공구.
10개의 객체 복제 1회
1만 개 대상 1회 복사
백만 개체 복제 1회
백만 개체 복사 5회
mapStruct
0ms
3ms
96ms
281ms
hutools의 BeanUtil
23ms
102ms
1734ms
8316ms
spring의 BeanUtils
2ms
47ms
726ms
3676ms
아파치의 BeanUtils
20ms
156ms
10658ms
52355ms
apache의 PropertyUtils
5ms
68ms
6767ms
30694ms
출처: MapStruct 사용 및 성능 테스트, BeanUtil 스톱
기본 사용
종속 구성
pom.xml 설정 아래 내용, 예에서 lombok을 사용했기 때문에 저는 lombok의 설정도 추가했습니다.
1.4.2.Final
1.18.20
org.projectlombok
lombok
${lombok.version}
true
org.mapstruct
mapstruct
${org.mapstruct.version}
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
org.projectlombok
lombok
${lombok.version}
org.mapstruct
mapstruct-processor
${org.mapstruct.version}
관례
@Data
public class Car {
private String make;
private int numberOfSeats;
private CarType type;
}
@Data
public class CarDto {
private String make;
private int seatCount;
private String type;
}
@Mapper
public interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);
// , @Mapping
@Mapping(source = "numberOfSeats", target = "seatCount")
CarDto carToCarDto(Car car);
}
@Test
public void shouldMapCarToDto() {
//given
Car car = new Car("Morris", 5, CarType.SEDAN);
//when
CarDto carDto = CarMapper.INSTANCE.carToCarDto(car);
//then
assertThat(carDto).isNotNull();
assertThat(carDto.getMake()).isEqualTo( "Morris");
assertThat(carDto.getSeatCount()).isEqualTo(5);
assertThat(carDto.getType()).isEqualTo("SEDAN");
}
봉인
위의 예에서 매번 사용할 때마다 한 번Mapper.INSTANCE
을 호출해야만 Mapper를 얻을 수 있다. 그러면 Mapper는 업무 코드와 결합되어 나중에 다른 도구를 교체하는 데 불리하다.우리는 대상 속성 복제 기능을 하나의 인터페이스Convert
로 추상화할 수 있다. 모든 빈은 Convert
의 하위 클래스이기 때문에 모든 빈은 대상 전환 능력을 가진다.public interface Convert extends Serializable {
/**
* JavaBean
*
* @param clazz class
* @param
* @return
*/
@SuppressWarnings({"unchecked", "rawtypes"})
default T convert(Class clazz) {
BeanConvertMapper mapper = BeanConvertMappers.getMapper(this.getClass(), clazz);
return (T) mapper.to(this);
}
}
BeanConvertMapper
대상 전환 인터페이스를 정의했다public interface BeanConvertMapper {
/**
* source to target
*
* @param source source
* @return target
*/
TARGET to(SOURCE source);
}
BeanConvertMappers
는 도구 종류로 Class
와 Class
를 통해 Mapper를 얻는 방법을 제공한다.@SuppressWarnings({"rawtypes", "unchecked"})
public class BeanConvertMappers {
public static BeanConvertMapper getMapper(Class sourceClass, Class targetClass) {
String key = MapperDefinition.generateKey(sourceClass, targetClass);
Class mapperClass = MapperDefinition.getMappers().get(key);
if (mapperClass == null) {
throw new IllegalArgumentException(StrUtil.format(" {} {} Mapper", sourceClass.getName(), targetClass.getName()));
}
return (BeanConvertMapper) Mappers.getMapper(mapperClass);
}
}
MapperDefinition
모든 유지보수Mapper
, 신규 Mapper
는 맵에 등록하면 됩니다.@SuppressWarnings("rawtypes")
public class MapperDefinition {
private static Map MAPPERS = new HashMap<>(16);
static {
registerMapper(CarDto.class, Car.class, CarDtoToCarMapper.class);
// Mapper
MAPPERS = MapUtil.unmodifiable(MAPPERS);
}
/* Mapper */
@Mapper
public interface CarDtoToCarMapper extends BeanConvertMapper {
}
/* Mapper */
public static Map getMappers() {
return MAPPERS;
}
public static String generateKey(Class sourceClass, Class targetClass) {
return sourceClass.getName() + targetClass.getName();
}
private static void registerMapper(Class sourceClass, Class targetClass, Class extends BeanConvertMapper> mapperClass) {
MAPPERS.put(generateKey(sourceClass, targetClass), mapperClass);
}
}
한층 더 최적화하다
위의 봉인은 Mapper 결합 문제를 해결했지만 Mapper를 정의할 때 대량의 템플릿 인터페이스가 존재하기 때문에 더 좋은 방법으로 해결할 수 있습니까?
내가 생각한 방안은 다음과 같다.
mapstruct 원리와 마찬가지로 mapstruct의 주석 프로세서에 앞서 주석을 통해 BeanConvertMapper
인터페이스를 생성하고 주석은 대체로 다음과 같으며 맵에 자동으로 주입됩니다.Mapper를 추가하려면 메모 하나만 정의하면 됩니다.@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface MapperDefinition {
/**
* Class
*
* @return Class
*/
Class> source();
/**
* Class
*
* @return Class
*/
Class> target();
}
더 좋은 방안이 있습니까? 함께 공유하세요.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
velocity map list 배열 작업
Velocity가 템플릿을 만들 때 맵,list 대상에 사용하고 출력 대상의 속성 값을 옮겨다니는 경우가 많다.스트리밍이 필요할 때, 스트리밍의 길이를 기록할 때, $velocity Count 내장 변수를 사용하여 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.
1.4.2.Final
1.18.20
org.projectlombok
lombok
${lombok.version}
true
org.mapstruct
mapstruct
${org.mapstruct.version}
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
org.projectlombok
lombok
${lombok.version}
org.mapstruct
mapstruct-processor
${org.mapstruct.version}
@Data
public class Car {
private String make;
private int numberOfSeats;
private CarType type;
}
@Data
public class CarDto {
private String make;
private int seatCount;
private String type;
}
@Mapper
public interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);
// , @Mapping
@Mapping(source = "numberOfSeats", target = "seatCount")
CarDto carToCarDto(Car car);
}
@Test
public void shouldMapCarToDto() {
//given
Car car = new Car("Morris", 5, CarType.SEDAN);
//when
CarDto carDto = CarMapper.INSTANCE.carToCarDto(car);
//then
assertThat(carDto).isNotNull();
assertThat(carDto.getMake()).isEqualTo( "Morris");
assertThat(carDto.getSeatCount()).isEqualTo(5);
assertThat(carDto.getType()).isEqualTo("SEDAN");
}
위의 예에서 매번 사용할 때마다 한 번
Mapper.INSTANCE
을 호출해야만 Mapper를 얻을 수 있다. 그러면 Mapper는 업무 코드와 결합되어 나중에 다른 도구를 교체하는 데 불리하다.우리는 대상 속성 복제 기능을 하나의 인터페이스Convert
로 추상화할 수 있다. 모든 빈은 Convert
의 하위 클래스이기 때문에 모든 빈은 대상 전환 능력을 가진다.public interface Convert extends Serializable {
/**
* JavaBean
*
* @param clazz class
* @param
* @return
*/
@SuppressWarnings({"unchecked", "rawtypes"})
default T convert(Class clazz) {
BeanConvertMapper mapper = BeanConvertMappers.getMapper(this.getClass(), clazz);
return (T) mapper.to(this);
}
}
BeanConvertMapper
대상 전환 인터페이스를 정의했다public interface BeanConvertMapper {
/**
* source to target
*
* @param source source
* @return target
*/
TARGET to(SOURCE source);
}
BeanConvertMappers
는 도구 종류로 Class
와 Class
를 통해 Mapper를 얻는 방법을 제공한다.@SuppressWarnings({"rawtypes", "unchecked"})
public class BeanConvertMappers {
public static BeanConvertMapper getMapper(Class sourceClass, Class targetClass) {
String key = MapperDefinition.generateKey(sourceClass, targetClass);
Class mapperClass = MapperDefinition.getMappers().get(key);
if (mapperClass == null) {
throw new IllegalArgumentException(StrUtil.format(" {} {} Mapper", sourceClass.getName(), targetClass.getName()));
}
return (BeanConvertMapper) Mappers.getMapper(mapperClass);
}
}
MapperDefinition
모든 유지보수Mapper
, 신규 Mapper
는 맵에 등록하면 됩니다.@SuppressWarnings("rawtypes")
public class MapperDefinition {
private static Map MAPPERS = new HashMap<>(16);
static {
registerMapper(CarDto.class, Car.class, CarDtoToCarMapper.class);
// Mapper
MAPPERS = MapUtil.unmodifiable(MAPPERS);
}
/* Mapper */
@Mapper
public interface CarDtoToCarMapper extends BeanConvertMapper {
}
/* Mapper */
public static Map getMappers() {
return MAPPERS;
}
public static String generateKey(Class sourceClass, Class targetClass) {
return sourceClass.getName() + targetClass.getName();
}
private static void registerMapper(Class sourceClass, Class targetClass, Class extends BeanConvertMapper> mapperClass) {
MAPPERS.put(generateKey(sourceClass, targetClass), mapperClass);
}
}
한층 더 최적화하다
위의 봉인은 Mapper 결합 문제를 해결했지만 Mapper를 정의할 때 대량의 템플릿 인터페이스가 존재하기 때문에 더 좋은 방법으로 해결할 수 있습니까?
내가 생각한 방안은 다음과 같다.
mapstruct 원리와 마찬가지로 mapstruct의 주석 프로세서에 앞서 주석을 통해 BeanConvertMapper
인터페이스를 생성하고 주석은 대체로 다음과 같으며 맵에 자동으로 주입됩니다.Mapper를 추가하려면 메모 하나만 정의하면 됩니다.@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface MapperDefinition {
/**
* Class
*
* @return Class
*/
Class> source();
/**
* Class
*
* @return Class
*/
Class> target();
}
더 좋은 방안이 있습니까? 함께 공유하세요.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
velocity map list 배열 작업
Velocity가 템플릿을 만들 때 맵,list 대상에 사용하고 출력 대상의 속성 값을 옮겨다니는 경우가 많다.스트리밍이 필요할 때, 스트리밍의 길이를 기록할 때, $velocity Count 내장 변수를 사용하여 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface MapperDefinition {
/**
* Class
*
* @return Class
*/
Class> source();
/**
* Class
*
* @return Class
*/
Class> target();
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
velocity map list 배열 작업Velocity가 템플릿을 만들 때 맵,list 대상에 사용하고 출력 대상의 속성 값을 옮겨다니는 경우가 많다.스트리밍이 필요할 때, 스트리밍의 길이를 기록할 때, $velocity Count 내장 변수를 사용하여 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.