프로젝트에서 DTO로만 구성된 두 개의 패키지 인 getters와 setters가있는 POJO가 있습니다. 단순한 자바 빈즈 (예 : Apache CXF가 웹 서비스 XSD 등을 생성하기 위해이를 사용하기 때문에)가 중요하지만, 그렇게 끔찍하고 오류가 발생하기 쉬운 프로그램이기도합니다.자바 빌더 생성기 문제
Foo foo = new Foo();
foo.setBar("baz");
foo.setPhleem(123);
return foo;
필자는 유창한 인터페이스와 빌더 객체를 선호하므로 maven/gmaven을 사용하여 DTO 용 빌더를 자동으로 작성합니다. 위의 코드에 대한하며,이 FooBuilder
이 자동으로 I는 다음과 같이 사용할 수있는, 생성됩니다
Foo foo = new FooBuilder()
.bar("baz")
.phleem(123)
.build();
또한 자동으로 생성 된 빌더에 대한 단위 테스트를 생성합니다. 단위 테스트는 위의 코드 (빌더 버전 및 비 빌더 버전)를 모두 생성하고 두 버전 모두 equals()
및 hashcode()
과 동등한 것임을 주장합니다. 달성 할 수있는 방법은 모든 속성 유형에 대해 기본적으로 전역 적으로 액세스 가능한지도를 만드는 것입니다. 다음과 같은 것 :
public final class Defaults{
private Defaults(){}
private static final Map<Class<?>, Object> DEFAULT_VALUES =
new HashMap<Class<?>, Object>();
static{
DEFAULT_VALUES.put(String.class, "baz");
// argh, autoboxing is necessary :-)
DEFAULT_VALUES.put(int.class, 123);
// etc. etc.
}
public static getPropertyValue(Class<?> type){
return DEFAULT_VALUES.get(type);
}
}
또 다른 중요한 점은 때때로 포자에 콜렉션 구성원이 있다는 것입니다. 예 :
foo.setBings(List<Bing> bings)
하지만 내 빌더에서 나는이이 사건에서 두 가지 방법으로 생성 할 수 싶습니다 일련의 방법과 추가 방법 : 나는에 사용자 정의 주석을 추가하여이 문제를 해결 한
fooBuilder.bings(List<Bing> bings); // set method
fooBuilder.addBing(Bing bing); // add method
을 Foo
@ComponentType(Bing.class)
private List<Bing> bings;
빌더 빌더 (SiC)의 속성 필드는 주석을 판독하고 생성하는 방법의 일반적인 유형으로의 값을 사용한다.
우리는 이제 질문에 가까워지고 있습니다. (죄송합니다. 간결함은 내 장점 중 하나가 아닙니다 .-)).
나는이 빌더 접근법이 둘 이상의 프로젝트에서 사용될 수 있다는 것을 알고 있으므로, 이것을 메이븐 플러그인으로 변환 할 생각이다. 나는 Maven 플러그인을 생성하는 방법에 대해 완벽하게 명확하므로 질문의 일부가 아니며 올바른 Java 소스 코드를 생성하는 방법도 아닙니다. 내 문제는 다음과 같습니다
-
가 나는 기본 클래스 (또는 유사한 메커니즘)가 필요합니다 : 어떻게 (프로젝트와 플러그인 사이에) 어떤 공통의 종속성을 도입하지 않고 위의 두 가지 문제를 해결할 수 생성 된 유닛 테스트에 대한 기본값을 얻으려면 (이것은 개념의 핵심 부분입니다. 완전히 테스트되지 않은 경우 자동으로 생성 된 빌더를 신뢰하지 않습니다). 각 프로젝트가 자체 도메인 객체를 가질 것이므로이 문제를 해결하기위한 훌륭하고 일반적인 방법을 찾도록 도와주세요.<Question>
제네릭 형식을 빌더 생성기와 통신하는 일반적인 방법이 필요합니다. 현재 주석 기반 버전은 만족스럽지 않습니다. 프로젝트와 플러그인 모두 동일한 주석을 인식해야하기 때문입니다.
</Question>
어떤 아이디어?
BTW : 빌더를 사용하는 진정한 요점은 객체를 변경할 수 없다는 것을 알고 있습니다. 나는 표준 자바 빈이 필요하기 때문에 나는 불변을 만들 수 없다. 그러나 나는 AspectJ를 사용하여 설정 메소드 나 생성자가 빌더를 제외한 모든 코드베이스에서 호출되지 않도록한다. 그래서 실용적인 목적의 객체는 불변이다. .
또한 예 : 기존 빌더 생성기 IDE 플러그인에 대해 알고 있습니다. 그건 내 목적에 맞지 않습니다. 자동화 된 솔루션이 필요합니다. 기본 코드가 변경 될 때마다 항상 최신 버전입니다.
Matt B가 내 빌더를 생성하는 방법에 대한 정보를 요청했습니다. 다음은 내가하는 일입니다.
리플렉션마다 클래스를 읽었으며 Introspector.getBeanInfo(clazz).getPropertyDescriptors()
을 사용하여 속성 설명자의 배열을 가져옵니다. 모든 빌더는 기본 클래스가 AbstractBuilder<T>
이고 위의 경우 이 Foo
이됩니다. 여기에 the code of the Abstract Builder class이 있습니다. PropertyDescriptor
배열의 모든 속성에 대해 속성 이름이있는 메서드가 생성됩니다.
public FooBuilder bar(String bar){
setProperty("bar", bar);
return this;
}
AbstractBuilder
의 build()
방법은 객체를 인스턴스화하고 속성지도의 모든 속성을 할당 :이 FooBuilder.bar(String)
의 구현 될 것입니다.
덧붙여 말하자면 자바 코드 (특히 단위 테스트의 거대한 세트)를 생성해야 할 때 grep/sed + python을 사용합니다 ... – khachik
저는 언어를 이해하는 기술을 사용하고 싶습니다. a) 반영 b) 소스 코드 파서 c) ASM과 같은 바이트 코드 도구 –
호기심에서 벗어나 Maven 플러그인이 빌더 클래스를 생성합니까? –