[Java] μ΄λ Έν μ΄μ (annotation)μ νμ©ν΄ μΈμ μ 보 κ°μ Έμ€κΈ°
νκ·Έ: Java
μΉ΄ν κ³ λ¦¬: Java
μ΄λ Έν μ΄μ μ μ§μ μ±
μ΄λ Έν μ΄μ μ μΈμ κΉμ§ μ μ§ν κ²μΈκ°
CLASS(default)
1
2
3
4
@Retention(value=RetentionPolicy.CLASS)
public @interface MyAnnotation {
String value() default "κΈ°λ³Έκ°μ¬μ©"; // μ΄λ
Έν
μ΄μ
μ¬μ©νλ μͺ½μμ λ°λ‘ κ° μ€μ μμ΄ κΈ°λ³Έκ°μΌλ‘ μ¬μ©.
}
μ»΄νμΌ κ³Όμ κΉμ§ μ μ§νκ² λ€. .class
νμΌμ μ΄λ
Έν
μ΄μ
μ ν¬ν¨νλ€. λ°μ΄νΈμ½λλ‘ μ΄λ
Έν
μ΄μ
νμΈ κ°λ₯. κ·Έλ¬λ λ°νμμ λ©λͺ¨λ¦¬μ λ‘λ©λμ§ μκΈ° λλ¬Έμ 리νλ μ
APIλ‘ μμλΌ μ μλ€.
SOURCE
1
2
3
4
@Retention(value=RetentionPolicy.SOURCE)
public @interface MyAnnotation {
String value();
}
μμ€ νμΌμλ§ λ¨κΈ΄λ€. .class
νμΌμ ν¬ν¨ μλλ€. μ»΄νμΌ μ μ κ±°λλ€. λ°μ΄νΈμ½λλ‘ νμΈ λΆκ°λ₯νλ€.
RUNTIME
1
2
3
4
@Retention(value=RetentionPolicy.RUNTIME)
public @interface MyAnnotation3 {
String value();
}
.class
νμΌμλ ν¬ν¨λκ³ , μ€νν λλ λ©λͺ¨λ¦¬μ λ‘λ©λλ€. κ·Έλ κΈ° λλ¬Έμ 리νλ μ
μΌλ‘ μ 보λ₯Ό μμλΌ μ μλ€.
리νλ μ μΌλ‘ μ΄λ Έν μ΄μ μ 보 κ°μ Έμ€κΈ°
1
2
3
4
@MyAnnotation
public class MyClass {
}
1
2
Class<?> clazz = MyClass.class;
clazz.getAnnotation(MyAnnotation.class);
μ΄λ Έν μ΄μ μ μ© λ²μ
@Target
μ μ¬μ©νμ¬ μ λ
Έν
μ΄μ
μ λΆμΌ μ μλ λ²μλ₯Ό μ μ΄ν μ μλ€.
μ’ λ₯ | λ²μ |
---|---|
ElementType.TYPE |
ν΄λμ€, μΈν°νμ΄μ€μ λΆμΌ μ μλ€. |
ElementType.FIELD |
νλ μ μΈ μμ λΆμΈλ€. |
ElementType.METHOD |
λ©μλ μ μΈ μμ λΆμΈλ€. |
ElementType.LOCAL_VARIABLE |
λ‘컬 λ³μ μμ λΆμΈλ€. |
{ElementType.LOCAL_VARIABLE, ElementType.PARAMETER, ElementType.FIELD} |
λ°°μ΄ ννλ‘ μ¬λ¬κ΅°λ°μ μ¬μ©νκ² ν μ μλ€. |
1
2
3
@Target({ElementType.LOCAL_VARIABLE, ElementType.PARAMETER, ElementType.FIELD})
public @interface MyAnnotation {
}
μ΄λ Έν μ΄μ νμ©
RetentionPolicy.RUNTIME
μ μ§ μ μ±
μ κ°μ§ μ΄λ
Έν
μ΄μ
μ νμ©νλ©΄ μ€νμ€μΈ μ΄ν리μΌμ΄μ
μμ νΉμ μ 보λ₯Ό μΆμΆν μ μλ€.
μλμ κ°μ΄ λ‘κ·ΈμΈν μ μ μ μΈμ
(httpSession) 체ν¬λ₯Ό μ΄λ
Έν
μ΄μ
κΈ°λ°μΌλ‘ λ°κΏ μ μλ€.
μ μ μΈμ μ 보 νμΈ
1
2
3
4
5
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginUser {
}
μ°μ μ΄λ
Έν
μ΄μ
μ μ μνλ€. ν΄λΉ μ΄λ
Έν
μ΄μ
μ νλΌλ―Έν° μμ λΆμΌ μ μλλ‘ @Target
μ μ§μ νκ³ ,
λ°νμ μμλ λ©λͺ¨λ¦¬ μμ μ΄λ
Έν
μ΄μ
μ λ³΄κ° μ μ§λλλ‘ @Retention
λ²μλ₯Ό μ§μ νλ€. μ΄λ₯Ό ν΅ν΄ 리νλ μ
μΌλ‘ μ΄λ
Έν
μ΄μ
μ 보λ₯Ό κ°μ Έμ¬ μ μλ€.
μ΄μ μ΄λ Έν μ΄μ μ μ΄μ©ν΄ 컨νΈλ‘€λ¬λ‘ λμ΄μ€λ DTO(Data Transfer Object) κ°μ²΄λ₯Ό κ²μ¦νκ² λλ€.
HandlerMethodArgumentResolver
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
@RequiredArgsConstructor
@Component
public class LoginUserArgumentResolver implements HandlerMethodArgumentResolver {
private final HttpSession httpSession;
@Override
public boolean supportsParameter(MethodParameter parameter) {
// νλΌλ―Έν°μ LoginUser μ΄λ
Έν
μ΄μ
μ΄ λΆμ΄ μλκ°?
boolean isLoginUserAnnotation = parameter.getParameterAnnotation(LoginUser.class) != null;
// νλΌλ―Έν° νμ
μ΄ SessionUser μΈκ°?
/* if(parameter.getParameterType == LoginUser.class) {return true} */
boolean isUserClass = SessionUser.class.equals(parameter.getParameterType());
// λλ€ μ°ΈμΌ κ²½μ° true λ°ν
return isLoginUserAnnotation && isUserClass;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
// μ supportsParameter λ©μλ true μ΄λ©΄ μ€ν
return httpSession.getAttribute("user");
}
}
HandlerMethodArgumentResolver
λ₯Ό ꡬννλ©΄ 컨νΈλ‘€λ¬ μ§μ
μ νλΌλ―Έν°λ₯Ό μ μ²λ¦¬ ν μ μλ€. μ μ½λμμλ μ μ μ 보λ₯Ό λ°λ DTO κ°μ²΄μ μ΄λ
Έν
μ΄μ
νμ
μ νμΈνκ³ ,
λ©μλμ νμ¬ νλΌλ―Έν° νμ
μ΄ SessionUser
μΈμ§ νμΈνλ€. 맨μμμ μ μν μ΄λ
Έν
μ΄μ
μ κ·μΉμ λ§λμ§ λ€μ νμΈνλ κ²μ΄λ€.
supportsParameter
κ° true λ₯Ό 리ν΄νκ²λλ©΄, resolveArgument
μμ μ€μ μΈμ
μ 보λ₯Ό κ°μ Έμ¨λ€.
WebConfig
1
2
3
4
5
6
7
8
9
10
11
12
@RequiredArgsConstructor
@Configuration
public class WebConfig implements WebMvcConfigurer {
private final LoginUserArgumentResolver loginUserArgumentResolver;
private final UserAgentArgumentResolver userAgentArgumentResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(loginUserArgumentResolver);
resolvers.add(userAgentArgumentResolver);
}
}
μμμ μ μν HandlerMethodArgumentResolver
ꡬν체λ₯Ό μ± μμ μ μΈμνκΈ° μν΄ WebMvcConfigurer
μΈν°νμ΄μ€λ₯Ό ꡬνν΄ λ£μ΄μ€λ€.
IndexController
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@RequiredArgsConstructor
@Controller
public class IndexController {
private final PostsService postsService;
private final HttpSession httpSession; // μ΄μ μΈμ
μμ λ°λ‘ κΊΌλ΄μ§ μκ³ μ΄λ
Έν
μ΄μ
μ μ΄μ©ν΄ κΊΌλΈλ€.
@GetMapping("/")
public String index(Model model, @LoginUser SessionUser user, @UserInfo String useragent) {
model.addAttribute("posts", postsService.findAllDesc());
// λ‘κ·ΈμΈν μ μ μΈμ
κ°μ Έμ€κΈ°
// -> μ΄λ
Έν
μ΄μ
κΈ°λ°(LoginUserArgumentResolver) μΌλ‘ λ³κ²½ μ 컨νΈλ‘€λ¬λ‘ μ λ¬λλ νλΌλ―Έν°μμ(user) λͺ¨λ κ²μ¦μ΄ λλ μνλ‘ κ°μ Έμ΄.
// - νλΌλ―Έν°λ μΈμ
μμ κ°μ Έμ΄(resolveArgument λ©μλ λ¦¬ν΄ λΆλΆ. httpsession.getAttribute)
// - μ μν μ΄λ
Έν
μ΄μ
μ΄ λΆμ΄μλμ§ / νμ
체ν¬.
// SessionUser user = (SessionUser) httpSession.getAttribute("user");
if (user != null) {
model.addAttribute("userName", user.getName());
}
model.addAttribute("userAgent", useragent);
return "index";
}
λ‘κ·ΈμΈ ν μ μ κ° μΈλ±μ€ νμ΄μ§ μ κ·Ό μ κ°λ¨νκ² μ΄λ Έν μ΄μ μΌλ‘ μΈμ μ 보λ₯Ό κ°μ Έμ¬ μ μλ€.
1
2
3
...
HttpServletRequest req = (HttpServletRequest) webRequest.getNativeRequest();
req.getHeader("User-Agent");
μΈμ μ 보λΏλ§ μλλΌ μ μ μ 보 λ±μ κ°μ Έμ€λ μ½λλ₯Ό resolver μ λ±λ‘ν΄ μ¬μ©ν μλ μλ€.
λκΈλ¨κΈ°κΈ°