2010-11-23 4 views
8

프로젝트에서 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 소스 코드를 생성하는 방법도 아닙니다. 내 문제는 다음과 같습니다

  1. <Question>

    가 나는 기본 클래스 (또는 유사한 메커니즘)가 필요합니다 : 어떻게 (프로젝트와 플러그인 사이에) 어떤 공통의 종속성을 도입하지 않고 위의 두 가지 문제를 해결할 수 생성 된 유닛 테스트에 대한 기본값을 얻으려면 (이것은 개념의 핵심 부분입니다. 완전히 테스트되지 않은 경우 자동으로 생성 된 빌더를 신뢰하지 않습니다). 각 프로젝트가 자체 도메인 객체를 가질 것이므로이 문제를 해결하기위한 훌륭하고 일반적인 방법을 찾도록 도와주세요.

  2. 제네릭 형식을 빌더 생성기와 통신하는 일반적인 방법이 필요합니다. 현재 주석 기반 버전은 만족스럽지 않습니다. 프로젝트와 플러그인 모두 동일한 주석을 인식해야하기 때문입니다.

</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; 
} 

AbstractBuilderbuild() 방법은 객체를 인스턴스화하고 속성지도의 모든 속성을 할당 :이 FooBuilder.bar(String)의 구현 될 것입니다.

+0

덧붙여 말하자면 자바 코드 (특히 단위 테스트의 거대한 세트)를 생성해야 할 때 grep/sed + python을 사용합니다 ... – khachik

+0

저는 언어를 이해하는 기술을 사용하고 싶습니다. a) 반영 b) 소스 코드 파서 c) ASM과 같은 바이트 코드 도구 –

+0

호기심에서 벗어나 Maven 플러그인이 빌더 클래스를 생성합니까? –

답변

1

Diezel을 보았습니까? 빌더 생성기입니다.

  1. 그것은 일반적인 유형을 처리하는, 그래서 질문이
  2. 그것은 설명 XML 파일을 기반으로 모든 인터페이스 및 구현 보일러 플레이트를 생성 여기 도움이 될 수 있습니다. 이 XML을 생성하기 위해 내부 검사를 통해 가능할 수도 있습니다 (또는 더 낮은 API로 직접 넘어갈 수도 있음)
  3. maven 플러그인으로 번들로 제공됩니다.
+0

굉장해 보이네. 고마워. –

2

POJO는 Java Bean Spoec을 따르지 않는 개체입니다. 즉. setters/getters가 없습니다.

JavaBeans에는 setter가 필요하지 않습니다. 호출자가 필요 없으면 생성하지 마십시오. (귀하의 작성자가 패키지 로컬 또는 개인 생성자를 호출하여 불변 객체를 생성 할 수 있음)

+0

OK, 그래서 POJO가 아닌 bean입니다. 그러나 우리가 사용하는 몇 가지 외부 도구는 (우리가 직접 사용하지 않아도) 거기에 세터가 의존하기 때문에 세터가 필요합니다. 당신은 다른 질문에 답하고 있습니다 (나는 당신의 대답이 무효하다는 말은 아니며, 저에게 무관합니다). 문제는 불변의 문제가 아니라 두 가지 구체적인 문제에 관한 것이 었습니다. 그 중 어느 것도 당신의 대답에 의해 다루어지지 않았습니다. –