[Spring] Annotation

서현서현·2022년 7월 13일
0

Spring

목록 보기
6/31
post-thumbnail

Annotation(@)

: 주석이란 의미. 특별한 의미/기능을 수행한다

특징

  • 컴파일러에게 코드작성 문법 에러를 체크하도록 정보를 제공한다.
  • 소프트웨어 개발 툴이 빌드나 배치시 코드를 자동으로 생성할 수 있도록 정보를 제공한다.
  • 실행시 특정기능을 실행하도록 정보를 제공한다

어떻게 작동하는가?

  1. 어노테이션을 정의한다
  2. 클래스에 어노테이션을 배치한다
  3. 코드 실행중에 Reflection을 이용하여 추가정보를 획득하여 기능을 실시한다


Reflection?

: 프로그램 실행중에 자신의 구조와 동작을 검사/조사/수정 하는 것이다.

역할

  • 프로그래머가 데이터를 보여주고, 다른포맷 데이터를 처리하고, 통신을위해 직렬화를 수행하고 bundling을 하기위해 일반 소프트웨어 라이브러리를 만들도록 돕는다.

  • 자바와 같은 객체지향 프로그래밍 언어에서는 Reflection을 사용하면 컴파일타임에 인터페이스, 필드, 메소드의 이름을 알지못해도 실행중에 클래스, 인터페이스, 필드 및 메소드에 접근 가능하다.

  • 새로운 객체의 인스턴스화 및 메소드 호출을 허용한다.

  • 객체지향 언어에서 멤버접근 가능성 규칙을 무시할 수 있다.

  • Spring의 BeanFactory라는 Container에서 객체가 호출되면 객체의 인스턴스를 생성하게 되는데, 이때 필요하다. 즉 프레임워크에서 유연성있는 동작을 위해 쓰인다.


Annotation 자체는 아무런 동작이없는 단순한 표식이나 Reflection을 이용하면 Annotation의 적용여부와 엘리먼트값을 읽고 처리할수있다.
Class에 적용된 Annotation 정보를 읽으려면 java.lang.Class 패키지의 배열을 얻어야한다

Reflection을 이용하면 Annotation 지정만으로도 원하는 클래스를 주입할 수 있다!

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



종류

@ComponentScan

: @Component@Service @Repository @Controlelr @Configuration이 붙은 클래스 Bean들을 찾아서 Context에 bean을 등록해주는 Annotation이다.
@Component Annotation이 있는 클래스에 대해 bean 인스턴스를 생성해준다!

ApplicationContext.xml에(root-context 인듯?)

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

위와 같이 bean을 등록하는 방법도 있고, Annotation을 직접 붙여서 등록하는 방법도 있다.

	<context:component-scan base-package="org.zerock.persistence"></context:component-scan>		
	<context:component-scan base-package="org.zerock.service"></context:component-scan>

base-package를 쓰면 해당 패키지 아래의 컴포넌트를 찾고 그과정을 spring-context-버전.jar에서 처리한다

스프링에서 @Component로 다 해결하지않고 @Service @Repository @Controlelr 등을 사용하는 이유는 두가지가 있다.
1. 예를들어 @Repository는 DAO의 메소드에서 발생할 수 있는 unchecked exception들을 스프링의 DataAccessException으로 처리할 수 있다.
2. 가독성면에서 우수하다

(CF) 자동으로 등록되는 Bean의 이름은 클래스의 첫문자가 소문자로 바뀐 이름이 자동 적용된다



@Component

: 개발자가 직접 작성한 Class를 Bean으로 등록하기 위한 어노테이션

@Component
public class Student {
    public Student() {
        System.out.println("hi");
    }
}

@Component(value="mystudent")
public class Student {
    public Student() {
        System.out.println("hi");
    }
}

Component에 대한 추가정보가 없다면 Class의 이름을 카멜케이스로 변경한것이 Bean id로 등록된다.
@Bean과 다르게 @Component는 name이 아닌 value를 이용해 Bean의 이름을 지정한다



@Bean

: 개발자가 직접 제어가 불가능한 외부 라이브러리 등을 Bean으로 만들려할때 사용된다.

사용법은 다음과같다.

@Configuration
public class ApplicationConfig {    
    @Bean
    public ArrayList<String> array(){
        return new ArrayList<String>();
    }   
}

ArrayList같은 라이브러리를 Bean으로 등록하기 위해 해당 라이브러리 객체를 반환하는 Method를 만들고 @Bean을 사용하면된다. 위의경우 @Bean에 아무런 값을 지정하지 않았으므로 Method이름을 카멜 케이스로 변경한것이 Bean id로 등록된다.

@Bean(name="myarray")

위와같이 name을 이용해 우너하는 아이디로 등록이 가능하다.



@Autowired

: 속성, setterMethod, 생성자에서 사용하며 Type에 따라 알아서 Bean을 주입해준다.
즉 스프링이 자동적으로 값을 할당한다.

Controller클래스에서 DAO나 Service에 관한 객체를 주입시킬때 많이 사용한다.
필드, 생성자, 입력파라미터가 여러개인 메소드에 적용 가능하다.
Type을 먼저 확인한 후 못찾으면 Name에 따라 주입한다. Name으로 강제하려면 @Qualifier를 명시한다.

따라서 Bean을 주입받는 방식은 3가지이다.
1. @Autowired
2. setter
3. 생성자(@AllArgsConstructor 사용) [권장]


@Inject

: @Autiwired와 비슷한 역할


@Controller

: 스프링의 컨트롤러를 의미한다. SpringMVC에서 Controller 클래스에 쓰인다.


@RestController

: 스프링에서 컨트롤러중 뷰로 응답하지않는 컨트롤러를 의미한다. method의 반환결과를 JSON형태로 반환한다.

이 어노테이션이 적혀있는 컨트롤러의 메소드는 HttpResponse로 바로 응답이 가능하다. @ResponseBody 역할을 자동적으로 해주는 어노테이션인것!

(CF) @Controller + @ResponseBody를 사용하면 @Responsebody 를 모든 메소드에서 적용한다


@Controller와 @RestController의 차이

  • @Controller
    : API와 view를 동시에 사용하는 경우에 해당한다. 대신 API서비스로 사용하는 경우 @ResponseBody를 사용하여 객체를 반환한다. view(화면) 리턴이 주 목적

  • @RestController
    : view가 필요없는 API만 지원하는 서비스에서 사용, Spring 4.0.1부터 제공하며 @RequestMapping 메소드가 기본적으로 @ResponseBody의미를 가정한다. data(json,xml등) 리턴이 주 목적


@Service

: Service Calss에서 쓰이며, 비즈니스 로직을 수행하는 Class라는것을 나타내는 용도이다.


@Repository

: DAO클래스에서 쓰인다. DataBase에 접근하는 Method를 갖고있는 클래스에서 쓰인다.


@EnableAutoConfiguration

: Spring Application Context를 만들때 자동으로 설정하는 기능을 켠다. classpath의 내용에 기반해서 자동으로 생성해주며 만약 tomcat-embed-core.jar가 존재하면 톰캣서버가 setting된다.


@Configuration

: 해당어노테이션을 클래스에 적용하고 @Bean을 클래스의 메소드에 적용하면 @Autowired로 Bean을 부를 수 있다.


@Required

: setter method에 적용해주면 Bean생성시 필수 프로퍼티임을 알린다.
즉 optional하지 않은, 꼭 필요한 속성을 정의한다.

영향을 받는 bean property를 구성할때 XML설정 파일에 반드시 property를 채워야한다.


@Qualifier("id123")

: @Autowired와 같이 쓰이며 같은타입 Bean객체가 있을때 해당 아이디를 적어 원하는 Bean이 주입될 수 있도록하는 어노테이션이다

같은타입의 Bean이 두개 이상 존재하는경우 스프링이 어떤 빈을 중비할지 알수없어 스프링 컨테이너를 초기화하는 과정에서 예외를 발생시킨다.

이경우 @Qualifier를 @Autowired와 함께 사용하여 정확히 어떤 빈을 사용할지 지정하여 특정 의존객체를 주입할 수 있도록 한다.

xml에서 qualifier value를 설정한다.
@Autowired 주입 대상에 @Qualifier을 설정한다.


@Resource

: @Autowired와 마찬가지로 빈객체를 주입해주는데, 차이점은 @Autowired는 타입, @Resource는 이름으로 연결

어노테이션 사용으로 인해 특정 프레임워크에 종속적인 어플리케이션을 구성하지 않기위해 @Resource 사용이 권장된다.

사용하고 싶다면 classPath 내에 jsr250-api.jar 파일을 추가한다. 필드, 입력 파라미터가 한개인 bean property setter method에 적용가능하다.


@PostConstruct, @PreConstruct

: 의존하는 객체를 생성한 이후 초기화 작업을 위해 객체 생성 전.후에 실행해야할 메소드 앞에 붙인다.


@PreDestroy

: 객체 제거 전에 해야할 작업을 수행하기위해 사용


@PropertySource

: 해당 프로퍼티 파일을 Environment로 로딩하게 해준다.

클래스에 @PropertySource("classpath:/settings.properties")라고 적고 클래스 내부에 @Resource를 Environment 타입의 멤버변수앞에 적으면 매핑된다.


@ConfigurationProperties

: yaml파일을 읽는다.디폴트로 classpath:application.properties파일이 조회된다.


@Lazy

: 지연로딩을 지원한다.
@Component@Bean과 같이 쓰는데 Class가 로드될때 스프링에서 바로 bean 등록을 마치는것이 아니라 실제로 사용될때 로딩이 이뤄지게 하는 방법


@Value

: properties에서 값을 가져와 적용할때 사용한다,

@Value("${value.from.file}")

private String valueFromFile;이라고 구성되어있으면 value.from.file의 값을 가져와 해당변수에 주입해준다.


@SpringBootApplication

: @Configuration, @EnableAutoConfiguration, @ComponentScan 3가지를 하나로 합친것


@RequestMapping

: 요청 URL을 어떤 method가 처리할지 mapping해주는 Annotation이다. Controller나 Controller의 method에 적용한다.

요청 받는 형식인 GET, POST, PUT, DELETE를 정의하기도 한다 (정의하지않으면 자동으로 GET)

@RequestMapping(value="/register", method= RequestMethod.GET )
@Controller
// 1) Class Level
//모든 메서드에 적용되는 경우 “/home”로 들어오는 모든 요청에 대한 처리를 해당 클래스에서 한다는 것을 의미
@RequestMapping("/home") 
public class HomeController {
    /* an HTTP GET for /home */ 
    @RequestMapping(method = RequestMethod.GET)
    public String getAllEmployees(Model model) {
        ...
    }
    /*
    2) Handler Level
    요청 url에 대해 해당 메서드에서 처리해야 되는 경우
    “/home/employees” POST 요청에 대한 처리를 addEmployee()에서 한다는 것을 의미한다.
    value: 해당 url로 요청이 들어오면 이 메서드가 수행된다.
    method: 요청 method를 명시한다. 없으면 모든 http method 형식에 대해 수행된다.
    */
    /* an HTTP POST for /home/employees */ 
    @RequestMapping(value = "/employees", method = RequestMethod.POST) 
    public String addEmployee(Employee employee) {
        ...
    }
}

@RequestMapping에 대한 모든 매핑정보는 스프링에서 제공하는 HandlerMapping Class가 가지고있다


@CookieValue

: 쿠키값을 파라미터로 전달받을 수 있는 방법이다.
해당 쿠키가 존재하지 않으면 500에러 발생.

속성은 required가 있는데, default는 true이다.
false를 적용하면 해당 쿠키값이 없을때 null로 입력받고 에러를 발생시키지 않는다.

// 쿠키의 key가 auth에 해당하는 값을 가져옴
public String view(@CookieValue(value="auth")String auth){...}; 

@CrossOrigin

: CORS 보안상의 문제로 브라우저에서 리소스를 현재 origin에서 다른곳으로의 AJAX 요청을 방지하는것

@RequestMapping이 있는곳에 사용하면 해당 요청은 타 도메인에서 온 ajax요청을 처리해준다.

//기본 도메인이 http://jeong-pro.tistory.com 인 곳에서 온 ajax요청만 받아주겠다.
@CrossOrigin(origins = "http://jeong-pro.tistory.com", maxAge = 3600)

@ModelAttribute

: view에서 전달해주는 파라미터를 class(VO/DTO)의 멤버변수로 바인딩해주는 어노테이션이다.

바인딩 기준은 <input name="id" />처럼 어떤 태그의 name값이 해당 class의 멤버 변수명과 일치해야하고 setMethod명도 일치해야한다.


@GetMapping

: @RequestMapping(Method=RequestMethod.GET_과 같다.

@PostMapping, @PutMapping, @PatchMapping, @DeleteMapping 도 있다


@SessionAttributes

: Session에 data를 넣을때 쓴다.


@Valid

: 유효성 검증이 필요한 객체임을 지정


@InitBinder

: @Valid 어노테이션으로 유효성 검증이 필요하다고 한 객체를 가져오기 전에 수행해야할 메소드를 지정


@RequestAttribute

: Request에 설정되어있는 속성값을 가져올수있다


@RequestBody

: 요청이 온 데이터(JSON이나XML)을 바로 Class나 Model로 매핑하기위한 어노테이션

POST나 PUT, PATCH로 요청을 받을때 요청에서 넘어온 body값들을 자바타입으로 파싱해준다

HTTP POST요청에 대해 request bosy에 있는 request message에서 값을 얻어와 매핑한다, RequestData를 바로 Model이나 클래스로 매핑한다.

이를테면 JSON이나 XML데이터를 적절한 messageConverter로 읽을때 사용하거나POJO형태 뎅터 전체로 받는 경우 사용한다


@RequestHeader

: Request의 헤더값을 가져온다. 메소드의 파라미터에 사용

//ko-KR,ko;q=0.8,en-US;q=0.6
@RequestHeader(value="Accept-Language")String acceptLanguage 로 사용 

@RequestParam

: @PathVariable과 비슷하다

request의 parameter에서 가져오는것이며, method의 파라미터에 사용된다. ?name=tom과 같은 쿼리파라미터를 파싱해준다


@RequestPart

: Request로 온 MultipartFile을 바인딩

@RequestPart("file") MultipartFile file

@ResponseBody

: HttpMessageConverter를 이용하여 JSON 혹은 xml로 요청에 응답할 수 있게 해주는 어노테이션

뷰가 아닌 JSON형식의 값을 응답할때 사용하는 어노테이션으로, 문자열 리턴시 그 값을 http response header가 아닌 respondebody에 들어간다.

이미 RestController 어노테이션이 붙어있다면 사용할필요없고 단순 Controller면 HttpResponse로 응답할 수 있게 해준다.
만약 객체를 리턴하는경우 JACKSON 라이브러리에 의해 문자열로 변환되어 전송된다. 컨텍스트에 설정된 viewResolver를 무시한다고 보면 된다.


@PathVariable

: method parameter 앞에 사용하면서 해당 URL에서 {특정값}을 변수로 받아올 수 있다.

@RequestMapping(value = "/some/path/{id}", method = RequestMethod.GET)
public ResponseEntity<?> someMethod(@PathVariable int id) {
}

HTTP 요청에 대해 매핑되는 request parameter값이 자동으로 바인딩된다. uri에서 각 구분자에 들어오는값을 처리해야할때 사용한다. REST API에서 값을 호출할때 주로 많이 사용된다.


@ExceptionHandler

: 해당 클래스 예외를 캐치해 처리


@ControllerAdvice

: Class위에 이 어노테이션을 붙이고 어떤 예외를 잡아낼것인지는 각 메소드 상단에 @ExceptionHandler(예외클래스명.class)를 붙여서 기술한다.


@RestControllerAdvice

: @ControllerAdvice + @ResponseBody


@ResponseStatus

: 사용자에게 원하는 response code와 reason을 return해주는 Annotation이다.


@EnableEurekaServer

: Eureka 서버로 만들어준다


@EnableDiscoveryClient

: Eureka 서버에서 관리될 수 있는 클라이언트임을 알려주기위한 어노테이션


@Transactional

: 데이터베이스 트랜잭션을 설정하고 싶은 method에 어노테이션을 적용하면 메소드 내부에서 일어나는 데이터베이스 로직이 전부 성공하게 되거나 데이터 베이스 접근중 하나라도 실패하면 다시 롤백할 수 있게 해주는 어노테이션

  • @Transaction(readOnly=true, rollbackFor=Exception.class)에서 readOnly는 읽기전용임을 알리고 rollbackFor는 해당 예외가 생기면 롤백하라는 소리이다.

  • @Transaction(noRollbackFor=Exception.class)는 해당 Exception이 나타나도 롤백하지 말라는 뜻이다.

  • @Transaction(timeout = 10)은 10초안에 해당 로직을 수행하지 못하면 롤백하라는 뜻이다.

메소드내에서 예외가 발생하면 해당 메소드에서 이루어진 모든 DB작업을 초기화한다, save메소드를 통해 10개를 등록해야 하는데 5번째에서 예외가 발생하면 앞에 저장된 4개까지 모두 롤백한다. 정확히 얘기하면 이미 넣은걸 롤백시키는건 아니고 정상적 처리가 되었을때만 DB에 커밋하며 그렇지 않은경우엔 커밋하지 않는것!

비지니스 로직과 트랜잭션 관리는 대부분 Service에서 관리한다. 따라서 DB데이터를 등록/수정/삭제하는 Service메소드는 @Transactional을 필수적으로 가져간다.


@Cacheable

: 메소드앞에 지정하면 해당 메소드를 최초 호출하면 캐시에 적재하고 다음부터는 동일한 메소드 호출이 있을때 캐시에서 결과를 가져와 리턴하므로 메소드 호출회수를 줄여준다.

주의할점은 입력이 같으면 항상 출력이 같은 메소드에만 적용해야한다. 메소드 호출에 사용되는 자원이 많고 자주 변경되지 않을때 사용하도록 하고 나중에 수정되면 캐시를 없애는 방법을 쓴다.


@CachePut

: 캐시를 업데이트 하기 위해서 메소드를 항상 실행하게 강제하는 어노테이션

해당 어노테이션이 있으면 메소드 호출을 항상 하게된다. 그러므로 @Cacheable과 상충되어 같이 사용하면 안됨


@CacheEvict

: 캐시에서 데이터를 제거하는 트리거로 동작하는 메소드에 붙인다.

캐시된 데이터는 언젠가 지워져야 함!(결과값 변경됐는데도 기존데이터 가져오니까)

물론 캐시설정에 만료시간을 줄수도 있다.

@CacheEvict(value="cacheKey"), @CacheEvict(value="cacheKey", allEntries=true)

allEntries는 전체 캐시를 지울지 여부를 선택하는 것이다.


@CacheConfig

: 클래스 레벨에서 공통의 캐시설정을 공유하는 기능


@Scheduled

: 정해진 시간에 실행하는 경우에 사용

@Scheduled(cron="0 0 07 * * ?")

초 분 시 일 월 요일 년(선택)에 해당 메소드 호출





출처 : https://velog.io/@gillog/Spring-Annotation-%EC%A0%95%EB%A6%AC

0개의 댓글