스프링 컨테이너 생성 → 스프링 빈 생성 → DI → 초기화 콜백 → Client가 사용 → 소멸전 콜백 → 스프링 종료
@Bean(initMethod = "init", destroyMethod = "close") public DBConnection databaseClient() { ... }
Bean이 존재할 수 있는 범위
Client가 Bean 요청시 스프링 DI 컨테이너가 의존관계, 초기화만 관리하여 반환하므로 Life Cycle로 설정한 종료 메서드를 호출하지 않는다!
매번 DI 완료된 새로운 Bean이 필요할 때 사용
외부 라이브러리이나 “org.aopalliance.intercept” 패키지로 편입됨
Supported Pointcut Designators
Spring AOP 에서 지원하는 Pointcut Designator(PCD)는 아래와 같다.
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern))
execution(public app.domain.Member app.repository.Repository.findById(String)) // - modifiers-pattern : public // - ret-type-pattern : app.domain.Member // - declaring-type-pattern : app.repository.Repository // - name-pattern : findById // - param-pattern : String
실행 순서는 기술한 순서와 같다.
만약 @Around 끼리 순서를 지정할 경우 @Order를 사용한다. 단. @Aspect 기반의 Class만 작동한다!
같은 개념으로, Advisor는 Spring AOP에서만 사용되는 개념
spring-boot-starter-aop 에 포함된 AnnotationAwareAspectjAutoProxyCreator 빈 후처리기가 작동하여
이후 프록시 객체 생성여부를 판단하고
Advisor가 포함된 객체 혹은 일반 객체가 스프링 컨테이너에 등록
의존성 주입시 사용.
Annotation | 설명 | 사용 |
---|---|---|
의존성 관련 | ||
@Qualifier | 다수의 Bean 있을 시, 특정 객체의 이름을 이용하여 구분지어 의존성 주입. @Qualifier 끼리 비교 → 이름 → 실패 ※ @Primary보다 우선순위가 높음 (더 상세하게 구현되었기 때문) | Instance variable, Method |
@Inject | @Autowired와 동일 기능. (Java에서 제공) 찾는 순서 : 타입 → @Qualifier→ 이름 → 실패 |
|
@Autowired | 주로 변수 위에 설정하여 해당 Type의 객체를 찾아서 자동으로 할당. (Spring에서 제공) 찾는 순서 : 타입 → 이름 → @Qualifier → 실패 |
|
@Resource | @Autowired와 @Qualifier 을 합한 기능. (1개, 다수 사용 가능.) 찾는 순서 : 이름 → 타입 → @Qualifier → 실패 |
|
@Value | Properties 값 주입 (사전에 root-context.xml에서 context:property-placeholder 설정 필요) | String variable |
Component 관련 | ||
@Component | component scan 설정 후 자동 Bean 생성. 기본적으로 DI 컨테이너가 Singleton으로 관리 | Class |
@Configuration | @Component 기능 및 Bean 설정 정보 관리 | |
@Primary | 같은 타입의 컴포넌트가 있을 시 우선권 명시 | |
@Controller | @Component 기능 및 Spring MVC의 Controller object 명시 (Web component) | |
@Repository | @Component 기능 및 DAO 객체를 Spring에 인식시킴 (Web component) | |
@Service | @Component 기능 및 Service 객체 명시. (Web component) 소스를 보면 @Component만 명시되어 있고, 딱히 하는 일이 없음. | |
Bean 관련 | ||
@Bean | 의존성을 관리할 Bean 생성. @Configuration과 함께 사용시 Singleton으로 관리 | Method |
@Scope | Bean 생명 주기 관리. 기본적으로 Singleton. Docs | |
REST 관련 | ||
@ResponseBody | Return type이 HTTP의 응답 메시지로 전송 (객체를 JSON Data로 전송시 사용) (3.0부터 지원) | Method, Return Type |
@RestController | View가 아닌 Data 자체를 반환 (jackson-databind와 사용하면 객체 자체를 자동으로 JSON Data로 반환) (4.0부터 지원) | |
@PathVariable | 현재 URI에서 원하는 Data 추출할 때 사용 | Parameter |
@RequestBody | request 문자열이 그대로 Paramter로 전달. 전송된 JSON Data를 객체로 변환. @ModelAttribute와 유사하지만 JSON에서 사용된다는 점이 차이 | |
@ModelAttribute | 자동으로 해당 Command 객체를 View까지 전달. Parameter에 적용된 경우 : Command 객체의 이름 변경(이 Annotation을 지정하지 않으면 클래스 이름의 첫 글자를 소문자로 변경한 이름이 자동으로 설정.) Method에 적용된 경우 : 반환된 객체를 View(JSP)에서 사용할 Data 설정. 이 때, @RequestMapping가 적용된 Method보다 먼저 호출된다. | Method, Parameter |
@RequestMapping | 특정 URI에 Mapping 되는 Class나 Method 명시 | Class, Method |
@RequestParam | request에서 특정 Parameter 값을 찾아낼 때 사용 (≒ request.getParameter()) Command 객체를 사용하지 못할 경우(Command Class에 없는 Parameter를 추출할 경우) 사용. | Parameter |
@RequestHeader | request에서 특정 HTTP 헤더 정보 추출할 때 사용 | |
@CookieValue | 현재 사용자의 쿠키가 존재하는 경우 쿠키의 이름을 이용해서 쿠키 값 추출 | |
@SessionAttribute | Session상에서 Model의 정보를 유지하고 싶은 경우 사용 | Class |
@InitBinder | Parameter를 수집해서 객체로 만들 경우에 Customizing | Method |
말그대로 model과 view를 저장하여 반환시켜 사용. 그러나 일반적으로는 Model 사용.
사용할 Data를 addAttribute()로 지정하고, 해당 Data를 보낼 view를 문자열로 반환시켜 사용.
말그래도 “Redirect” 시키며 Attribute 추가.
상태 코드 제어. AJAX 연동(@RestController)에서 Data를 첨부하여 사용. 특이점으로 상태코드 상관없이 Data는 전송된다.
package io.github.ledyx.controller; import javax.inject.Inject; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import io.github.ledyx.domain.ReplyVO; import io.github.ledyx.service.ReplyService; @RestController @RequestMapping("/replies") public class ReplyController { @Inject private ReplyService service; @RequestMapping(value = "/", method = RequestMethod.POST) public ResponseEntity<String> add(@RequestBody ReplyVO vo) { ResponseEntity<String> entity = null; try { service.add(vo); entity = new ResponseEntity<>("SUCCESS", HttpStatus.OK); } catch (Exception e) { e.printStackTrace(); entity = new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); } return entity; } }