일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 카카오APi
- XML Core
- java컴파일
- 반응형웹
- 데이터규정
- 자바
- 웹프로그래밍
- 데이터베이스
- 스프링프레임워크
- Servlet
- JSP
- JSTL
- 공문서작성규정
- Session
- HTTP
- xml
- 프로그래밍용어
- Multipart
- XML DOM
- 자바스크립트
- Java
- 데이터포맷
- java annotation
- Request/Response Header
- 세션
- JavaScript
- 데이터문서포맷
- Database
- Ajax
- xml mapping
- Today
- Total
KyungHwan's etc.
어노테이션(Annotation) 본문
JDK1.5 부터 제공된 기능인 어노테이션은 @(;AT) 으로 시작하는 주석의 한 형태를 말한다. @Override, @SuppressWarnings("") 과 같은 어노테이션에 익숙할 것이다
어노테이션은 메타데이터 한 형태로, 프로그램에 대한 정보를 제공하지만, 그 프로그램의 일부는 아니다. 어노테이션을 설정한 코드에 직접적인 영향을 미치지는 않는다.
Annotation의 의미
Annotation의 사전적 의미는 주석이다
하지만 Java에서의 Annotation은 조금 더 고차원적이다.
자바 소스 코드에 추가하여 사용할 수 있는 메타 데이터의 일종이다. 즉, 자바 소스 코드에 들어가면서 데이터의 데이터를 정의해줄 수 있다.
Annotation의 역사
Annotation은 JDK 버전 1.5부터 언어 자체에서 사용할 수 있게 되었다.
JDK 1.6 버전에서부터는 javac 컴파일러에 통합되었다.
Annotation 의 동작
소스코드에서 클래스, 메소드, 변수, 매개 변수 및 패키지에 annotation을 달 수 있다.
Annotation은 컴파일러에 의해 생성되는 .class 파일에 포함되며 그 .class 파일을 통해 읽혀진다.
JVM 실행 시, annotation은 보관되며 reflection을 통해 자세하게 읽을 수 있다.
Built-in annotations
Java 언어에 내장되어 있는 annotation을 의미한다.
7개의 주석 중 3개는 java.lang에 있고 4개는 java.lang.annotation에 있다.
@Override
메소드가 Override 되어있는지 확인합니다. Override 되어있는 메소드를 찾을 수 없는 경우 컴파일 오류가 발생한다.
@Deprecated
메소드를 쓸모 없는 것으로 표시한다. 메소드가 사용되면 컴파일 경고를 발생시킨다.
더 이상 지원하지 않거나 만들고 나니 별로 안 좋은 부분이 있거나, 더 좋은 해결법이 생겼으니, 사용하지 말라는 의미한다.
@SuppressWarnings
annotation의 매개 변수(여러 종류가 있음)에 지정된 대로 컴파일러에게 컴파일 경고를 내지 않도록 지시합니다. 그래서 이를 적용하면 경고 메세지가 있어도 경고를 내지 않는다.
@Retention
표시된 annotation이 어떻게 저장될지 지정한다.
@Retention(RetentionPolicy.RUNTIME)
@Documented
문서(JavaDoc) 안에 현재 annotation의 존재를 표기하도록 지정한다.
@Target
annotation이 적용될 Java 요소를 제한하기 위해 annotation을 표시한다.
@Target({ElementType.METHOD})
@Inherited
annotation이 달린 클래스의 하위 클래스에 상속될 annotation을 표시합니다.(기본적으로 annotation은 하위 클래스에 상속되지 않는다.)
Java 7부터 3가지 Built-in annotation이 추가되었다.
@SafeVarargs
Java 7부터 generics varargs 매개 변수를 사용하여 호출되는 메소드 또는 생성자를 Suppress warnings 한다.
@FunctionalInterface
Java 8 이후 type 선언이 functional interface가 되도록 한다.
@Repeatable
Java 8 이후 annotation을 동일한 선언에 두 번 이상 적용할 수 있도록 지정한다.
Annotation Example
Built-in annotations
이 예제는 @Override annotation의 사용법을 보여준다. @Override를 쓰면 컴파일러가 부모 클래스에서 똑같은 메소드가 있는지 검사를 하게 된다. 이 경우, Cat 클래스의 gettype() 메소드가 Animal 클래스의 getType()을 대체하지 않기 때문에 오류가 발생한다. @Override annotation이 없을 경우, Cat 클래스에 새로운 gettype() 메소드가 작성된다.
public class Animal {
public void speak() {
}
public String getType() {
return "Generic animal";
}
}
public class Cat extends Animal {
public void speak() { // This is a good override.
System.out.println("Meow.");
}
public String gettype() { // Compile-time error due to mistyped name.
return "Cat";
}
}
Custom annotations
Annotation의 선언은 일반 인터페이스 선언과 유사한다.
@가 interface 키워드 앞에 온다.
아래 예시에는 메소드를 선언할 때 어노테이션이 있게 된다.
메소드 선언에 throws 절이 없어야 한다.
반환 유형은 Primitives, String, Class, enums, annotation, array 등으로 제한된다.
// @Twizzle is an annotation to method toggle().
public void toggle() {
}
// Declares the annotation Twizzle.
public @interface Twizzle {
}
annotation은 key-value 들을 선택적으로 포함시킬 수 있다.
// Same as: @Edible(value = true)
true) (
Item item = new Carrot();
public @interface Edible {
boolean value() default false;
}
first = "Oompah", last = "Loompah") (
Book book = new Book();
public @interface Author {
String first();
String last();
}
annotation 자체는 언제 어디서 사용될 수 있는지 나타 내기 위해서 annotate할 수 있다
annotation은 사용자 정의 클래스 및 메소드에 동작을 편리하게 적용하는 방법으로 프레임 워크에서 자주 사용된다.
Java 소스 코드가 컴파일되면 annotation processor라는 컴파일러 플러그인이 annotation을 처리할 수 있다. 이 processor는 정보 메세지를 생성하거나 Java 소스파일이나 리소스를 추가로 생성할 수 있으며 컴파일 및 처리가 가능하고 annotation이 달린 코드 자체도 수정할 수 있다. Java 컴파일러는 Annotation이 Class 또는 RUNTIME**의 RetentionPolicy**를 갖는 경우 조건부로 메타 데이터를 .class 파일에 저장한다. 이로써 나중에 JVM 또는 다른 프로그램은 메타 데이터를 찾아 프로그램 요소와 상호작용하거나 동작을 변경하는 방법을 결정할 수 있다.
그래서 annotation을 정의할 때 @Retention(RetentionPolicy.RUNTIME) 을 써줘야 한다.
annotation processor를 사용해 annotation을 처리하기 위해서 Java 프로그래머는 reflectio을 사용하여 annotation을 처리하는 자체 코드를 작성 할 수 있다.
java.lang.reflect 패키지에는 AnnotatedElement라는 인터페이스가 포함되어 있는데 이 인터페이스를 이용해 annotation을 reflect하면서 읽을 수 있다.
AnnotatedElement 인터페이스는 RUNTIME retention을 갖는 annotation에 대한 접근을 제공한다. 이 접근은 getAnnotation, getAnnotations, isAnnotationPresent 메소드에서 제공한다. 왜냐하면 annotation 들은 클래스와 마찬가지로 바이트 코드 파일로 컴파일되고 저장되기 때문에 이런 메소드에 의해 리턴된 어노테이션은 일반 Java 객체와 마찬가지로 처리될 수 있다.
만약 직접 만든 annotation을 쓰고싶다면 따로 컨테이너 클래스를 만들어 주입해야 한다.
Reflection
컴퓨터 과학에서 reflection이란 프로그램이 실행 중에 자신의 구조와 동작을 검사하고, 조사하고, 수정하는 것이다.
reflection은 프로그래머가 데이터를 보여주고, 다른 포맷의 데이터를 처리하고, 통신을 위해 serialization(직렬화)를 수행하고, bundling을 하기 위해 일반 소프트웨어 라이브러리를 만들도록 도와준다.
Java와 같은 객체 지향 프로그래밍 언어에서 reflection을 사용하면 컴파일 타임에 인터페이스, 필드, 메소드의 이름을 알지 못해도 실행 중에 클래스, 인터페이스, 필드 및 메소드에 접근할 수 있다. 또한 새로운 객체의 인스턴스화 및 메소드 호출을 허용한다.**
C# 및 Java와 같은 일부 객체 지향 프로그래밍 언어에서는 reflection을 사용하여 멤버 접근 가능성 규칙을 무시할 수 있다. 예를 들어 reflection을 사용하면 서드 파티 라이브러리의 클래스에서 private 필드의 값을 변경할 수 있다.
스프링에서 BeanFactory라는 Container를 공부할 때 객체가 호출되면 객체의 인스턴스를 생성하게 되는데 이 때 필요하게 된다. 즉, 프레임워크에서 유연성있는 동작을 위해 쓰게 된다.
java.lang.reflect 패키지를 통해 reflection 기능을 제공한다.
Class.forName(), getName(), getModifier(), getPackage() 등등 여러 메소드로 정보를 얻을 수 있다.
리플렉션을 이용하면 어노테이션 지정만으로도 원하는 클래스를 주입할 수 있다.
// Without reflection
Foo foo = new Foo();
foo.hello();
// With reflection
Object foo = Class.forName("complete.classpath.and.Foo").newInstance();
// Alternatively: Object foo = Foo.class.newInstance();
Method m = foo.getClass().getDeclaredMethod("hello", new Class<?>[0]);
m.invoke(foo);
1. 어노테이션 생성하기
1-1. 인터페이스를 생성한다.
1-2. interface앞에 @붙인다
public @interface DeokNotation {
}
1-3. 어노테이션 정보로 사용 할 변수를 선언해준다.
public @interface DeokNotation {
String name();
}
1-4. 어노테이션 변수에 디폴트 값 지정해주기
int height() default 183;
완성 된 DeokNotation
public @interface DeokNotation { String name(); int height() default 183;
}
1-5 어노테이션 사용하기
name="김덕주", height = 183) public class { (
}
2.어노테이션의 구성요소
어노테이션은 어디에 붙일지 (클래스 or 메소드, 변수)를 정하는 @Target과 어노테이션 정보가 언제 까지 유지를 할지에 대한 @Retention를 구성요소로 가지고 있다.
@Target
이름 | 대상 |
---|---|
TYPE | 클래스,인터페이스 |
FIELD | 참조 변수혹은 eunm |
METHOD | 메소드 |
PARAMETER | 메소드 매개변수 |
CONSTRUCTOR | 클래스 생성자 |
LOCAL_VARIABLE | 메소드 내부 변수 |
ANNOTATION_TYPE | Annotation 타입 |
PACKAGE | 패키지 |
Sample Code
ElementType.METHOD) public @interface DeokNotation { String name(); int height() default 183; } (
예로 정의한 @Traget 코드는 메소드에만 어노테이션을 표기 할 수 있다.
메소드 이외에는 컴파일 오류가 발생한다.
@Targer으로 여러 개를 지정하고 싶을때는 어떻게 해야할까?
Field로 지정하고 싶고, 메소드로 지정해야 할 경우 이럴때는 target을 배열로 여러 개를 지정해주면 된다.
ElementType.METHOD, ElementType.FIELD}) ({
@Retention
이름 | 유지범위 |
---|---|
SOURCE | 컴파일러가 사용하고 클래스 파일에는 포함되지 않음(단순 주석용,컴파일용) |
CLASS | 컴파일시 클래스 파일 안에 포함되나 VM에서 무시함 |
RUNTIME | 컴파일시 포함되고 VM에서 인식함 |
Sample Code
RetentionPolicy.RUNTIME) (
5. 자바 어노테이션을 사용해보기
위에서 작성한 내용을 기반으로 자바 어노테이션을 만들어 보고 그 어노테이션(주석)을 클래스가 읽어보는것을 해보자.
1. 사람이라는 클래스를 작성한다. Class name : Person
사람 클래스는 키 : height, 몸무게 : weight, 이름 : name 이라는 변수를 가진다.
2. 사람정보 어노테이션을 만든다. 어노테이션 이름 : PersonInfo
이 어노테이션은 필드에 부착이 되며 int 타입과 String 타입의 요소를 가진다.
int 타입 변수명 : setInt
String 타입 변수명 : setString
3.PersonInfo 어노테이션을 사람 클래스의 변수에 부착한다.
4.ReadAnnotation**이라는 클래스를 생성하여 Person에 부착한 어노테이션 정보를 읽는다.**
Person
public class Person {
setInt = 183) (
protected int height; // 키
setInt = 88) (
protected int weight; // 몸무게
setString = "김덕주") (
protected String name; // 이름
}
PersonInfo
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
RetentionPolicy.RUNTIME) (
ElementType.FIELD) (
public @interface PersonInfo {
int setInt() default 0;
String setString() default "";
}
ReadAnnotation
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class ReadAnnotation {
public static void main(String[] args) {
//1.클래스 정보를 가져온다.
Class person = Person.class;
//2.클래스에 선언 된 필드를 찾는다.
Field[] fields = person.getDeclaredFields();
//3.필드에 어노테이션이 부착되어 있는지 확인
for(Field f: fields) {
Annotation[] anno = f.getAnnotations();
try{
//4.PersonInfo annotation을 가져옴
PersonInfo pInfo = (PersonInfo)anno[0];
//출력
System.out.print(pInfo.setInt());
System.out.print(pInfo.setString());
}catch(Exception e)
{
e.printStackTrace();
}
}
}
}
Reference
https://namkyujin.com/2017-03-14/java-annotation/
https://ko.wikipedia.org/wiki/%EC%9E%90%EB%B0%94_%EC%95%A0%EB%84%88%ED%85%8C%EC%9D%B4%EC%85%98
https://en.wikipedia.org/wiki/Java_annotation
https://en.wikipedia.org/wiki/Reflection_(computer_programming)
https://medium.com/@ggikko/java-%EC%BB%A4%EC%8A%A4%ED%85%80-annotation-436253f395ad
·
'Java > 스프링프레임워크' 카테고리의 다른 글
스프링프레임워크 - Spring Framework: annotation 정리 (0) | 2018.06.01 |
---|---|
스프링프레임워크 -Mybatis (0) | 2018.05.31 |
스프링프레임워크 용어 간단히 정리 (0) | 2018.05.31 |
스프링(Spring)을 통한 의존성(DI) 주입 (0) | 2018.05.31 |
스프링프레임워크 - DAO, DTO ,VO (0) | 2018.05.30 |