1.    Handlebar.js


Handlebar.js(이하 Handlebar) 자바스크립트의 템플릿 엔진 하나이다. 먼저 템플릿 엔진이라 하면 프로그램 로직과 프레젠테이션 계층을 분리하기위한 수단이다.  Mustache 기반으로 구현한 템플릿 인자, 여기서 Mustache 콧수염모양의 {{ }} Bracket 이용하여 data 표현하는 것을 의미한다. 이를 이용하면 html페이지에서 HTML+Bracket 구성으로 디자이너와 개발자가 협업할 때도 디자이너에게도 이해하기 쉬운 구조로써 협업을 하는데도 도움이 된다.

 

 

2.    기본 사용방법


표현식


  • {{title}}  같은 형태로 표현되며, 현재 Context에서 title이라는 Property를 찾아서 대체하는 의미이다.

  • {{section.title}}  같은 형태로 dot(.)으로 분리된 경로 탐색도 가능하다. 현재 Context에서 section을 찾고, title 속성을 찾아서 대체하는 의미이다.

  • {{section/title}} 과 같이 / 문법을 사용할 수 있다. 식별자는 아래 열거된 UniCode를 제외하고 모두 사용 가능하다.

    • Whitespace ! " # % & ' ( ) * + , . / ; < = > @ [ \ ] ^ ` { | } ~

  • 배열 접근 표현식을 통해 Property에 접근할 수 있다section 배열의 3번째 titles 의 모든 property 를 context 로 갖으면서 subject 와 body 에 접근한다.

1

2

3

4

5

6

{{#each section.[3].titles}}

  <h1>{{subject}}</h1>

  <div>

    {{body}}

  </div>

{{/each}}

cs


  • {{! }} 블록으로 주석을 추가할 수 있다.

  • {{log}} 블록으로 템플릿 출력 시 로깅할 수 있다.

  • {{{body}}} HTML요소는 자동으로 이스케이프 시켜준다.

 

Helper


  • Helper 기본적으로 다른 개발 언어의 함수라고 볼 수 있다.

  • 기본 문법은 아래와 같다.

 

1

{{{ Helper_Name param1 parm2 ... }}}

cs

  • HandlebarsHelper Call은 단순한 식별자이며, 0개 이상의 Parameter를 받을 수 있다. 그리고 구분은 공백으로 한다. 나누게 된다.  Handlesbars는 위에 설명한 표현식과 완전히 동일한 방법으로 사용된다.

  • 반복과 같은 다른 템플릿엔진에서 제공하는 Helper 존재한다.

 

1

2

3

{{#each userlist}}

{{user}}

{{/each}}

cs

 

아래 코드는 link라는 Helper story라는 Parameter를 넣어 실행시킨 결과를 출력하라는 의미이다.

 

1

{{{link story}}}

cs

 

link helper  Handlebars.registerHelper(Helper_Name, function ) 으로 등록한다.

 

1

2

3

4

5

Handlebars.registerHelper('link'function(object) {

  return new Handlebars.SafeString(

    "<a href='" + object.url + "'>" + object.text + "</a>"

  );

});

Colored by Color Scripter

cs

 

Helper 는 최종 Parameter들로 key-value pair hash 를 전달할 수도 있다.

 

1

{{{link "See more..." href=story.url class="story"}}}

cs

 

이럴 경우 Helper 함수에서는 hash 부분을 하나의 object 로 받아서, object.hash 로 접근하여 key-value pair 에 대한 context를 얻을 수 있다.

 

1

2

3

4

5

6

7

8

9

10

11

Handlebars.registerHelper('link'function(text, options) {

  var attrs = [];

 

  for(var prop in options.hash) {

    attrs.push(prop + '="' + options.hash[prop] + '"');

  }

 

  return new Handlebars.SafeString(

    "<a " + attrs.join(" "+ ">" + text + "</a>"

  );

});

Colored by Color Scripter

cs

 

Subexpressions


Handlebars subexpression을 제공한다. 이는 단일 mustache를 이용하여 복합 Helper를 호출할 수 있다. 그리고 내부 Helper의 결과를 외부 Helper Parameter로 전달 할 수 있다. Subexpression ( )로 구분한다.

1

{{outer-helper (inner-helper 'abc''def' }}

cs

 

위 코드에서는 inner-helper는 문자열 'abc'를 받는 Helper로 호출이 되며 이 결과는 outer-helper의 첫번째 Parameter로 전달된다. 그리고 'def'는 두번째 Parameter 로 전달된다.

 

Whitespace Control


템플릿의 공백은 특정 mustache스테이트먼트의 각 부분에서 ~ 문자를 브레이스{의 의해서 생략이 될 수 있다.

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

{

    nav: [

        {url: 'foo', test: true, title: 'bar'},

        {url: 'bar'}

    ]

}

 

 

{{#each nav ~}}

    <a href="{{url}}">

        {{~#if test}}

            {{~title}}

        {{~^~}}

            Empty

        {{~/if~}}

    </a>

{{~/each}}

Colored by Color Scripter

cs

 

출력 결과 뉴라인과 포매팅된 공백 처리 결과는 아래와 같다.

 

1

<a href="foo">bar</a><a href="bar">Empty</a>

cs

 

이 확장은 라인 처리의 기본적인 동작이며 "standalone" Helper이다.

 

1

2

3

4

5

6

7

8

9

{{#each nav}}

    <a href="{{url}}">

        {{#if test}}

            {{title}}

        {{^}}

            Empty

        {{/if}}

    </a>

{{~/each}}

cs

 

 

결과는 아래와 같다.

 

1

2

3

4

5

6

<a href="foo">

    bar

</a>

<a href="bar">

    Empty

</a>

cs

 

 

 

Escaping


Handlebars컨텐츠는 하나 혹은 두개의 방법으로 이스케이프 될 수 있다. 이는 인라인 이스케이프 혹은 raw block helpers이다. 인라인 escape prefixing mustache블록으로 \으로 시작하는 블록이다. Raw block {{{{ mustache 브레이스로 생성된다.

 

1

2

3

4

\{{escaped}}

{{{{raw}}}}

    {{escaped}}

{{{{/raw}}}}

cs



 

참고사이트

 

페이지: http://handlebarsjs.com/

깃허브: https://github.com/wycats/handlebars.js/

http://ohgyun.com/427

http://sailboat-d.tistory.com/40

http://jojoldu.tistory.com/23

http://tmondev.blog.me/220398995882

http://programmingsummaries.tistory.com/381

https://blog.outsider.ne.kr/939

http://aroundck.tistory.com/957

http://uncle-bae.blogspot.kr/2016/06/handlebars-expression.html

 

'IT > Handlebar' 카테고리의 다른 글

Handlebars 코딩 해보기  (0) 2017.01.12

Lombok Annotation

@Getter / @Setter

Annotation Getter Setter 함수를 생성해준다. 그리고  AccessLevel(PUBLIC, PROTECTED, PACKAGE, PRIVATE) 지정을 통해서 접근 레벨도 제한할 있으며, 특정 필드는 메서드 생성이 필요하지 않을 경우 AccessLevel.NONE 설정을 통해 자동 메소드 생성을 막을 있다.

 

아래 예제 소스를 통해 어떻게 활용하는지 알아보자.

Lombok Code

 

1

2

@Getter @Setter private boolean employed = true;

@Setter(AccessLevel.PROTECTED) private String name;

cs

 

Java Code

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

private boolean employed = true;

private String name;

 

public boolean isEmployed() {

    return employed;

}

 

public void setEmployed(final boolean employed) {

    this.employed = employed;

}

 

protected void setName(final String name) {

    this.name = name;

}

Colored by Color Scripter

cs

 

 

@NonNull

@NonNull Class위에서는 사용이 불가능하며, Class 내에서 필요한 멤버에 직접 사용해야 한다. @NonNull 사용하면 @Setter 생성되는 setter 메서드에 전달되는 parameter @NonNull 붙게 된다. 하지만 해당 setter 메서드에 null 넘기도록 코드를 작성 수도 있다. , 컴파일 시점에서 적용되지 않고 runtime시에 Null Check 하여 NullPointerException 발생하도록 하는 것이다. , setXXX null을 넘겨줄 경우 if (xxx==null) 체크 코드가 들어가서 throw new NullPointerException("XXX")을 던져준다. 멤버 변수에 붙여줄 경우에는 그 필드를 꼭 받도록 생성자가 수정된다.

 

Lombok Code

1

2

@Getter @Setter @NonNull

private List<Person> members;

cs

 

Java Code

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

@NonNull

private List<Person> members;

 

public Family(@NonNull final List<Person> members) {

    if (members == nullthrow new java.lang.NullPointerException("members");

    this.members = members;

}

    

@NonNull

public List<Person> getMembers() {

    return members;

}

 

public void setMembers(@NonNull final List<Person> members) {

    if (members == nullthrow new java.lang.NullPointerException("members");

    this.members = members;

}

Colored by Color Scripter

cs

 

 

@ToString

@ToStringClass에 있는 필드들을 검사해서 문자열로 변환해주는 toString() 메소드를 생성한다. 상호 참조하는 객체의 경우에는 toString() 호출시 Stack Overflow 가 발생할 수 있다. 한쪽 객체에서 다른 쪽 객체에 대해 @ToString(excluded={“propertyName”}) 형태로 제외토록 만들어야 한다.

@EqualsAndHashCode(of = {})로 꼭 필요한 필드만 비교하도록 처리한다.

 

 

Lombok Code

1

2

3

4

5

6

@ToString(callSuper=true,exclude="someExcludedField")

public class Foo extends Bar {

    private boolean someBoolean = true;

    private String someStringField;

    private float someExcludedField;

}

Colored by Color Scripter

cs

 

 

Java Code

1

2

3

4

5

6

7

8

9

10

11

12

public class Foo extends Bar {

    private boolean someBoolean = true;

    private String someStringField;

    private float someExcludedField;

    

    @java.lang.Override

    public java.lang.String toString() {

        return "Foo(super=" + super.toString() +

            ", someBoolean=" + someBoolean +

            ", someStringField=" + someStringField + ")";

    }

}

Colored by Color Scripter

cs

 

 

@EqualsAndHashCode

@EqualsAndHashCode은 코드에서 객체 비교 등의 용도로 사용되는 equals(), hashCode() 메소드의 코드를 생성해준다. 그리고 exclude={field-name,..}을 통해 특정 필드를 제외할 수도 있다.

 

Lombok Code

1

2

3

4

5

6

7

8

9

10

11

12

13

@EqualsAndHashCode(callSuper=true,exclude={"address","city","state","zip"})

public class Person extends SentientBeing {

    enum Gender { Male, Female }

 

    @NonNull private String name;

    @NonNull private Gender gender;

    

    private String ssn;

    private String address;

    private String city;

    private String state;

    private String zip;

}

Colored by Color Scripter

cs

 

 

Java Code

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

public class Person extends SentientBeing {

    

    enum Gender {

        /*public static final*/ Male /* = new Gender() */,

        /*public static final*/ Female /* = new Gender() */;

    }

    @NonNull

    private String name;

    @NonNull

    private Gender gender;

    private String ssn;

    private String address;

    private String city;

    private String state;

    private String zip;

    

    @java.lang.Override

    public boolean equals(final java.lang.Object o) {

        if (o == thisreturn true;

        if (o == nullreturn false;

        if (o.getClass() != this.getClass()) return false;

        if (!super.equals(o)) return false;

        final Person other = (Person)o;

        if (this.name == null ? other.name != null : !this.name.equals(other.name)) return false;

        if (this.gender == null ? other.gender != null : !this.gender.equals(other.gender)) return false;

        if (this.ssn == null ? other.ssn != null : !this.ssn.equals(other.ssn)) return false;

        return true;

    }

    

    @java.lang.Override

    public int hashCode() {

        final int PRIME = 31;

        int result = 1;

        result = result * PRIME + super.hashCode();

        result = result * PRIME + (this.name == null ? this.name.hashCode());

        result = result * PRIME + (this.gender == null ? this.gender.hashCode());

        result = result * PRIME + (this.ssn == null ? this.ssn.hashCode());

        return result;

    }

}

Colored by Color Scripter

cs

 

 

 

@Data

@DataClass에 정의된 모든 필드에 대한 getter, setter toString, equals, hashCode, final로 지정됐거나 @NonNull로 명시된 필드에 대한 값을 받는 생성자 메소드 코드를 생성해 준다. , 앞에서 배웠던 @Getter, @Setter, @NonNull, @EqualsAndHashCode, @ToString 에 대한 걸 모두 해주는 Annotation이다.

 

Lombok Code

1

2

3

4

5

6

@Data(staticConstructor="of")

public class Company {

    private final Person founder;

    private String name;

    private List<Person> employees;

}

Colored by Color Scripter

cs

 

 

Java Code

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

public class Company {

    private final Person founder;

    private String name;

    private List<Person> employees;

    

    private Company(final Person founder) {

        this.founder = founder;

    }

    

    public static Company of(final Person founder) {

        return new Company(founder);

    }

    

    public Person getFounder() {

        return founder;

    }

    

    public String getName() {

        return name;

    }

    

    public void setName(final String name) {

        this.name = name;

    }

    

    public List<Person> getEmployees() {

        return employees;

    }

    

    public void setEmployees(final List<Person> employees) {

        this.employees = employees;

    }

    

    @java.lang.Override

    public boolean equals(final java.lang.Object o) {

        if (o == thisreturn true;

        if (o == nullreturn false;

        if (o.getClass() != this.getClass()) return false;

        final Company other = (Company)o;

        if (this.founder == null ? other.founder != null : !this.founder.equals(other.founder)) return false;

        if (this.name == null ? other.name != null : !this.name.equals(other.name)) return false;

        if (this.employees == null ? other.employees != null : !this.employees.equals(other.employees)) return false;

        return true;

    }

    

    @java.lang.Override

    public int hashCode() {

        final int PRIME = 31;

        int result = 1;

        result = result * PRIME + (this.founder == null ? this.founder.hashCode());

        result = result * PRIME + (this.name == null ? this.name.hashCode());

        result = result * PRIME + (this.employees == null ? this.employees.hashCode());

        return result;

    }

    

    @java.lang.Override

    public java.lang.String toString() {

        return "Company(founder=" + founder + ", name=" + name + ", employees=" + employees + ")";

    }

}

Colored by Color Scripter

cs

 

 

 

 

@Value
@ValueImmutable Class을 생성해준다.  @Data와 비슷하지만 모든 필드를 기본적으로 Private Final로 로 하고, Setter 함수를 생성하지 않고, Class또한 Final로 지정하는 것만 빼고 동일하다.

 

Lombok Code

1

2

3

4

5

6

7

8

9

10

11

12

13

@Value public class ValueExample {

   String name;

   @Wither(AccessLevel.PACKAGE) @NonFinal int age;

   double score;

   protected String[] tags;

   

   @ToString(includeFieldNames=true)

   @Value(staticConstructor="of")

   public static class Exercise<T> {

     String name;

     T value;

   }

}

Colored by Color Scripter

cs

 

Java Code

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

public final class ValueExample {

   private final String name;

   private int age;

   private final double score;

   protected final String[] tags;

   

   @java.beans.ConstructorProperties({"name""age""score""tags"})

   public ValueExample(String name, int age, double score, String[] tags) {

     this.name = name;

     this.age = age;

     this.score = score;

     this.tags = tags;

   }

   

   public String getName() {

     return this.name;

   }

   

   public int getAge() {

     return this.age;

   }

   

   public double getScore() {

     return this.score;

   }

   

   public String[] getTags() {

     return this.tags;

   }

   

   @java.lang.Override

   public boolean equals(Object o) {

     if (o == thisreturn true;

     if (!(o instanceof ValueExample)) return false;

     final ValueExample other = (ValueExample)o;

     final Object this$name = this.getName();

     final Object other$name = other.getName();

     if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;

     if (this.getAge() != other.getAge()) return false;

     if (Double.compare(this.getScore(), other.getScore()) != 0return false;

     if (!Arrays.deepEquals(this.getTags(), other.getTags())) return false;

     return true;

   }

   

   @java.lang.Override

   public int hashCode() {

     final int PRIME = 59;

     int result = 1;

     final Object $name = this.getName();

     result = result * PRIME + ($name == null ? 43 : $name.hashCode());

     result = result * PRIME + this.getAge();

     final long $score = Double.doubleToLongBits(this.getScore());

     result = result * PRIME + (int)($score >>> 32 ^ $score);

     result = result * PRIME + Arrays.deepHashCode(this.getTags());

     return result;

   }

   

   @java.lang.Override

   public String toString() {

     return "ValueExample(name=" + getName() + ", age=" + getAge() + ", score=" + getScore() + ", tags=" + Arrays.deepToString(getTags()) + ")";

   }

   

   ValueExample withAge(int age) {

     return this.age == age ? this : new ValueExample(name, age, score, tags);

   }

   

   public static final class Exercise<T> {

     private final String name;

     private final T value;

     

     private Exercise(String name, T value) {

       this.name = name;

       this.value = value;

     }

     

     public static <T> Exercise<T> of(String name, T value) {

       return new Exercise<T>(name, value);

     }

     

     public String getName() {

       return this.name;

     }

     

     public T getValue() {

       return this.value;

     }

     

     @java.lang.Override

     public boolean equals(Object o) {

       if (o == thisreturn true;

       if (!(o instanceof ValueExample.Exercise)) return false;

       final Exercise<?> other = (Exercise<?>)o;

       final Object this$name = this.getName();

       final Object other$name = other.getName();

       if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;

       final Object this$value = this.getValue();

       final Object other$value = other.getValue();

       if (this$value == null ? other$value != null : !this$value.equals(other$value)) return false;

       return true;

     }

     

     @java.lang.Override

     public int hashCode() {

       final int PRIME = 59;

       int result = 1;

       final Object $name = this.getName();

       result = result * PRIME + ($name == null ? 43 : $name.hashCode());

       final Object $value = this.getValue();

       result = result * PRIME + ($value == null ? 43 : $value.hashCode());

       return result;

     }

     

     @java.lang.Override

     public String toString() {

       return "ValueExample.Exercise(name=" + getName() + ", value=" + getValue() + ")";

     }

   }

}

Colored by Color Scripter

cs

 

 

@Cleanup

@Cleanup Local 변수에 붙이면 Cleanup code 가 현재 code 가 종료될 때 자동으로 호출해주도록 한다. 그리고 close() method가 있으면 해당 변수 scope 끝까지 자동으로 try { } 로 묶어주고 finally 블록에서 field.close() 를 넣어준다. 이것은 컴파일 타임에 close()를 호출하도록 하는 것이므로 별도의 interface가 필요로 하지 않는다.

close() 가 없고 다른 method cleanup 을 수행할 경우 @Cleanup("dispose") 같이 method명을 작성해주면 해당 메소드를 호출해준다. , 만약 destroy() 을 불러야 하는 경우라면 @Cleanup("destroy")라고 작성해 주면 된다. , try 블록에서 예외가 발생했고 cleanup 메서드에서도 예외가 발생할 경우 cleanup 메서드에서 발생한 예외는 완전히 무시된다. 그러므로 @Cleanup 완전히 의존하는 것은 위험하다.

 

 

Lombok Code

1

2

3

4

5

6

7

8

9

public void testCleanUp() {

    try {

        @Cleanup ByteArrayOutputStream baos = new ByteArrayOutputStream();

        baos.write(new byte[] {'Y','e','s'});

        System.out.println(baos.toString());

    } catch (IOException e) {

        e.printStackTrace();

    }

}

Colored by Color Scripter

cs

 

 

Java Code

1

2

3

4

5

6

7

8

9

10

11

12

13

public void testCleanUp() {

    try {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        try {

            baos.write(new byte[]{'Y''e''s'});

            System.out.println(baos.toString());

        } finally {

            baos.close();

        }

    } catch (IOException e) {

        e.printStackTrace();

    }

}

Colored by Color Scripter

cs

 

 

 

@Synchronized

@Synchronizedstatic instance lock 오브젝트를 자동으로 생성해주고, Annotation을 메서드에 적용할 경우에는 메서드 Body synchronized 키워드로 감싸준다.

여기서 관심있게 볼 부분은 new Object() serialize 되지 않는 것을 고려하여 $lock, instance용 오브젝트를 new Object[0]로 선언해준다는 것이다. Annotation된 메소드가 정적이면 Lombok을 통해 $LOCK, Class 오브젝트가 자동으로 작성되어 @Synchronized 메소드와 동기화시킨다.

만약 별도의 lock 객체를 생성해서 특정 메서드에만 적용하고 싶다면 (read-lock 같은 경우를 위해) @Synchronized("lock-object-name") 형식으로 쓰면 된다. 대신 lock-object-name은 프로그래머가 직접 필드를 선언해야만 한다. 예를 들면, @Synchronized("myObject") myObject오브젝트와 대조하여 @Synchronized 메소드를 동기화한다.

 

 

 

Lombok Code

1

2

3

4

5

6

private DateFormat format = new SimpleDateFormat("MM-dd-YYYY");

 

@Synchronized

public String synchronizedFormat(Date date) {

    return format.format(date);

}

Colored by Color Scripter

cs

 

 

Java Code

1

2

3

4

5

6

7

8

private final java.lang.Object $lock = new java.lang.Object[0];

private DateFormat format = new SimpleDateFormat("MM-dd-YYYY");

 

public String synchronizedFormat(Date date) {

    synchronized ($lock) {

        return format.format(date);

    }

}

Colored by Color Scripter

cs

 

 

@SneakyThrows
잘 일어나지 않는 checked exceptions을 처리해준다. 물론 IDE을 통해 checked exception Quick-Fix로 고치면 자동으로 e.printStackTrace()을 붙여준다.

 

 

Lombok Code

1

2

3

4

@SneakyThrows

public void testSneakyThrows() {

    throw new IllegalAccessException();

}

Colored by Color Scripter

cs

 

 

Java Code

1

2

3

4

5

6

7

public void testSneakyThrows() {

    try {

        throw new IllegalAccessException();

    } catch (java.lang.Throwable $ex) {

        throw lombok.Lombok.sneakyThrow($ex);

    }

}

Colored by Color Scripter

cs

 

val

Local 변수 선언을 val을 이용해서 하면 초기화 값을 이용하여 변수 타입을 유추해서 final로 생성해 준다. 즉 자바스크립트에서 var 키워드와 동일한 기능을 한다고 생각하면 된다.

 

Lombok Code

1

2

3

4

5

6

7

8

9

10

11

12

13

14

public String example() {

    val example = new ArrayList<String>();

  example.add("Hello, World!");

  val foo = example.get(0);

  return foo.toLowerCase();

}

public void example2() {

  val map = new HashMap<Integer, String>();

  map.put(0"zero");

  map.put(5"five");

  for (val entry : map.entrySet()) {

    System.out.printf("%d: %s\n", entry.getKey(), entry.getValue());

  }

}

Colored by Color Scripter

cs

 

 

Java Code

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

public String example() {

     final ArrayList<String> example = new ArrayList<String>();

     example.add("Hello, World!");

     final String foo = example.get(0);

     return foo.toLowerCase();

}

   

public void example2() {

     final HashMap<Integer, String> map = new HashMap<Integer, String>();

     map.put(0"zero");

     map.put(5"five");

     for (final Map.Entry<Integer, String> entry : map.entrySet()) {

       System.out.printf("%d: %s\n", entry.getKey(), entry.getValue());

     }

}

Colored by Color Scripter

cs

 

 

 

 

@Log

자동으로 logging을 위한 필드인 private static final Logger log 가 추가됩니다. 이후 로그를 출력하려는 곳에서 log.error(), log.warn(), log.debug(), log.info() 형태로 사용하면 된다.

이외에도 다양한 로그 타입을 지원한다. (@CommonsLog, @JBossLog, @Log4j, @Log4j2, @Slf4j, @XSlf4j)

 

Lombok Code

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

@Log

public class LogExample {

   public static void main(String... args) {

     log.error("Something's wrong here");

   }

}

 

@Slf4j

public class LogExampleOther {

   public static void main(String... args) {

     log.error("Something else is wrong here");

   }

}

 

@CommonsLog(topic="CounterLog")

public class LogExampleCategory {

   public static void main(String... args) {

     log.error("Calling the 'CounterLog' with a message");

   }

}

Colored by Color Scripter

cs

 

 

Java Code

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

public class LogExample {

   private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());

   

   public static void main(String... args) {

     log.error("Something's wrong here");

   }

}

 

public class LogExampleOther {

   private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExampleOther.class);

   

   public static void main(String... args) {

     log.error("Something else is wrong here");

   }

}

 

public class LogExampleCategory {

   private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog("CounterLog");

 

   public static void main(String... args) {

     log.error("Calling the 'CounterLog' with a message");

   }

}

Colored by Color Scripter

cs

 

 

@Builder
@Builder AnnotationClass에 대한 복잡한 Builder API들을 자동으로 생성해 준다. 그리고 @BuilderClass 뿐만 아니라, 생성자, 메서드에도 사용할 수 있다. 추가적으로 @Singular Annotation도 제공한다. @Singular@ Builder Annotation을 사용한 Class/Method/Constructor에서 Collection 객체에만 사용할 수 있다. Collection 변수에 @Singular을 설정하면 setter 함수 대신 두 종류의 Adder 함수와 Clear함수를 생성해 준다. Adder 함수는 1개 또는 모두 요소를 추가하는 두 종류의 Adder 함수가 생성된다. 그리고 Collectionclear 하는 함수도 생성해준다. 현재 Lombok에서 지원하는 Collectionjava.utilGuava(com.google.common.collect) 만을 지원한다.

 

 

Lombok Code

1

2

3

4

5

6

@Builder

public class BuilderExample {

   private String name;

   private int age;

   @Singular private Set<String> occupations;

}

Colored by Color Scripter

cs

 

 

Java Code

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

public class BuilderExample {

   private String name;

   private int age;

   private Set<String> occupations;

   

   BuilderExample(String name, int age, Set<String> occupations) {

     this.name = name;

     this.age = age;

     this.occupations = occupations;

   }

   

   public static BuilderExampleBuilder builder() {

     return new BuilderExampleBuilder();

   }

   

   public static class BuilderExampleBuilder {

     private String name;

     private int age;

     private java.util.ArrayList<String> occupations;

     

     BuilderExampleBuilder() {

     }

     

     public BuilderExampleBuilder name(String name) {

       this.name = name;

       return this;

     }

     

     public BuilderExampleBuilder age(int age) {

       this.age = age;

       return this;

     }

     

     public BuilderExampleBuilder occupation(String occupation) {

       if (this.occupations == null) {

         this.occupations = new java.util.ArrayList<String>();

       }

       

       this.occupations.add(occupation);

       return this;

     }

     

     public BuilderExampleBuilder occupations(Collection<extends String> occupations) {

       if (this.occupations == null) {

         this.occupations = new java.util.ArrayList<String>();

       }

 

       this.occupations.addAll(occupations);

       return this;

     }

     

     public BuilderExampleBuilder clearOccupations() {

       if (this.occupations != null) {

         this.occupations.clear();

       }

       

       return this;

     }

 

     public BuilderExample build() {

       // complicated switch statement to produce a compact properly sized immutable set omitted.

       // go to https://projectlombok.org/features/Singular-snippet.html to see it.

       Set<String> occupations = ...;

       return new BuilderExample(name, age, occupations);

    }

     

     @java.lang.Override

     public String toString() {

       return "BuilderExample.BuilderExampleBuilder(name = " + this.name + ", age = " + this.age + ", occupations = " + this.occupations + ")";

     }

   }

}

Colored by Color Scripter

cs

 

 

그 이외에 Lombok의 공식적인 Feature은 아니지만 테스트 중인 다양한 feature들도 있다.

 

참고 사이트

 

https://projectlombok.org/features/

http://jnb.ociweb.com/jnb/jnbJan2010.html

https://blogs.idincu.com/dev/?p=17

http://edoli.tistory.com/99

http://kwonnam.pe.kr/wiki/java/lombok?s[]=lombok

 

'IT > Lombok' 카테고리의 다른 글

LOMBOK 이란  (0) 2017.01.06

LOMBOK

자바 개발자라면 누구나 경험 했을 것이다. 간단한 Class 하나 만드는데 특히 VO, DTO, Entity등의 Class 만들 getter/setter 함수 등을 기계적으로 생성했어야 했던 귀찮은 작업들을.

 

1

2

3

4

5

6

7

8

9

public class inconvenientClass{

    private T a;

    public T getA () {

     return a;

    } 

    public void setA(T a) {

     this.a = a;

    }

}

cs

 

코드와 같이 단순히 변수 하나만 정의된 간단한 class이지만, 값을 핸들링 하기 위해 쓸데없이 작성해야 하는 코드가 많았다.

물론 IDE 자동생성 기능을 통해 쉽게 생성할 있지만, 여전히 변수 명이 변경되면 다시 getter/setter 함수를 변경해줘야 하는 번거로움이 발생한다. 이를 해결해 주기 나온 Lombok 이다. 간단하게 이해하면 Getter/Setter 자동 생성라이브러리라고 생각하면 된다. 물론 다양한 기능을 제공한다. 그럼 지금부터 하나씩 알아 가보자

Lombok이란?

Lombok 자바에서 @Getter, @Setter 같은 annotation 기반으로 관련 기존 DTO, VO, Domain Class 작성할 , 멤버 변수에 대한 Getter/Setter Method, Equals(), hashCode(), ToString() 멤버 변수에 값을 설정하는 생성자 등등을 자동으로 생성해 주는 라이브러리다.

먼저 Lombok 사용한 코드와 사용하지 않는 코드를 먼저 보자

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

public class BasicSampel {

    private Integer id;

    private String name;

 

    public Integer getId() {

        return id;

    }

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    @Override

    public boolean equals(Object o) {

        if (this == o) return true;

        if (!(o instanceof LombokSampel)) return false;

 

        LombokSampel that = (LombokSampel) o;

 

        if (id != null ? !id.equals(that.id) : that.id != nullreturn false;

        return name != null ? name.equals(that.name) : that.name == null;

    }

 

    @Override

    public int hashCode() {

        int result = id != null ? id.hashCode() : 0;

        result = 31 * result + (name != null ? name.hashCode() : 0);

        return result;

    }

}

 

Colored by Color Scripter

cs

 

아래 코드는 Lombok 사용했다. 깜짝 놀랄 정도로 소스가 짧아졌다는 눈으로 확인할 있을 것이다.

 

1

2

3

4

5

6

7

8

9

import lombok.Data;

import lombok.Setter;

import lombok.EqualsAndHashCode;

 

@Data

public class LombokSampel {

    private Integer id;

    private String name;

}

Colored by Color Scripter

cs

 

샘플 코드를 통해 확인했듯이 Lombok 사용한 코드가 매우 짧아졌다. 필요한 곳에 적당한 Lombok Annotation 붙여 주기만 하면 끝이다. Annotation 문자 그대로 이해할 있을 정도로 매우 직관적이다. @Getter  getter() 함수를, @Setter setter() 함수를 생성하고 @EqualsAndHashCode  equals() 함수와 hashCode() 함수를 자동으로 생성해준다.

그럼 Lombok에서 제공해주는 Annotation 무엇이 있는지 알아보자.


'IT > Lombok' 카테고리의 다른 글

Lombok Annotation  (0) 2017.01.10

+ Recent posts