0116 ~ 0129
# 0116 ~ 0129
# 0117 - Objects.requireNonNull
์๋ฐ7์ ์ถ๊ฐ๋ Object
ํด๋์ค์์ ์ ๊ณตํ๋ ๋(Null) ์ฒดํฌ๋ฅผ ์ํ ๋ฉ์๋. ํ๋ผ๋ฏธํฐ๋ก ์
๋ ฅ๋ ๊ฐ์ด null์ด๋ผ๋ฉด NPE(NullPointerException)๊ฐ ๋ฐ์ํ๊ณ , ๊ทธ๋ ์ง ์๋ค๋ฉด ์
๋ ฅ๊ฐ์ ๊ทธ๋๋ก ๋ฐํํ๋ ๊ฐ๋จํ ๋ฉ์๋์ด๋ค. requireNonNull
์ ์๋์ ๊ฐ์ด ์ธ๊ฐ์ง๋ก ์ค๋ฒ๋ก๋ฉ ๋์ด์๋ค.
๋ฆฌํดํ์ | ๋ฉ์๋ |
---|---|
T | requireNonNull(T obj) |
T | requireNonNull(T obj, String message) |
T | requireNonNull(T obj, Supplier msgSupplier) |
์ฒซ๋ฒ์งธ ๋ฉ์๋๋ null์ ์ ๋ฌํ๋ฉด ๋ฉ์ธ์ง๊ฐ ๋น์ด์๋ NPE ์์ธ๋ฅผ ๋์ง๋ค.
Objects.requireNonNull(null);
// java.lang.NullPointerException
2
๋๋ฒ์งธ ๋ฉ์๋๋ null์ ์ ๋ฌํ๋ฉด, ๋๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌํ ๋ฌธ์์ด์ ๋ฉ์ธ์ง๋ก ๊ฐ๋ NPE ์์ธ๋ฅผ ๋์ง๋ค.
Objects.requireNonNull(null, "null์ ์ ๋ฌ๋ ์ ์์ต๋๋ค!");
// java.lang.NullPointerException: null์ ์ ๋ฌ๋ ์ ์์ต๋๋ค!
2
์ธ๋ฒ์งธ ๋ฉ์๋๋ null์ ์ ๋ฌํ๋ฉด, ๋๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌํ Supplier ๋ฅผ ๊ตฌํํ ์ต๋ช ํจ์์ ๋ฐํ๊ฐ์ ๋ฉ์ธ์ง๋ก ๊ฐ๋ NPE ์์ธ๋ฅผ ๋์ง๋ค.
Objects.requireNonNull(null, () -> "null์ ์ ๋ฌ๋ ์ ์์ต๋๋ค!");
// java.lang.NullPointerException: null์ ์ ๋ฌ๋ ์ ์์ต๋๋ค!
2
# [ ์ฌ์ฉ ์ด์ ]
๋น ๋ฅธ ์คํจ
null์ ์ฐธ์กฐํ์ฌ ์์ธ๊ฐ ๋ฐ์ํ๊ฑฐ๋ requireNonNull์ null์ด ๋ค์ด๊ฐ๋ ๋๊ฐ์ด NPE๊ฐ ๋ฐ์ํ๋ ๊ฒ์ ๋ง์ฐฌ๊ฐ์ง์ด๋ ์ฌ์ฉํ๋ ์ด์ ๋ ๋น ๋ฅธ ์คํจ (Fail-Fast) ์ด๋ค. ๋๋ฒ๊น ์ ์ฝ๊ฒ ํ๊ธฐ ์ํด์๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ ์ฆ๊ฐ์ ์ผ๋ก ๊ฐ์งํ ํ์๊ฐ ์๋ค. ๋ฌธ์ ์ ์์ธ๊ณผ ๋ฌธ์ ์ ๋ฐ์ ์ง์ ์ด ๋ฌผ๋ฆฌ์ ์ผ๋ก ๋ฉ๋ฆฌ ๋จ์ด์ ธ ์๋ค๋ฉด ๋๋ฒ๊น ํ๊ธฐ ํ๋ค ๊ฒ์ด๋ค.
๋ช ์์ฑ๊ณผ ๊ฐ๋ ์ฑ
๋น ๋ฅธ ์คํจ๋ if ๋ฌธ์ผ๋ก๋ ์ถฉ๋ถํ ๊ตฌํ์ด ๊ฐ๋ฅํ์ง๋ง, ์๋์ผ๋ก ๋์ฒดํฌํ ์ฝ๋๋ณด๋ค ๊ฐ๋ ์ฑ์ด ๋ ์ข๊ณ , ๋ช ์์ ์ด๋ค.
# 0119 - Security์์ hasRole, hasAuthority ์ฐจ์ด
ํํ Spring Securit์์ ์ ๊ณตํ๋ ์ญํ (Role)๊ณผ ๊ถํ(Authority)์ ํผ๋ํ์ฌ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์๋ฐ ๋น์ทํ๋ฉด์๋ ๋ค๋ฅด๋ค.
- role ๊ด๋ จ ์ค์ ์ ์คํ๋ง ์ํ๋ฆฌํฐ 4์ด์ ๋ฒ์ ๋ถํฐ ์๋์ผ๋ก ์ ๋์ฌ์ 'ROLE_'์ ์ถ๊ฐํ๋ค.
- authority๋ 'ROLE_' ์ถ๊ฐ๋ก ์ฌ์ฉํ์ง ์๋๋ค.
- hasAuthority('ROLE_ADMIN')์ hasRole('ADMIN')์ ๊ฐ์ ์๋ฏธ์ด๋ค.
# 0124 - self-invocation
# [ Spring AOP์ ๋์ ๊ณผ์ ]
Spring AOP๋ ํ๋ก์ ๊ธฐ๋ฐ์ผ๋ก IoC ์ปจํ ์ด๋์์ ๋น์ ์์ฑํ๋ ์์ ์ AOP๋ฅผ ์ ์ฉํ ์ง ์ฌ๋ถ๋ฅผ ํ๋จํ์ฌ ํ๋ก์ ๋น์ ์์ฑํด์ค๋ค.
์ด ๊ณผ์ ์์ JDK Proxy์ CGLIB ๋ ์ค์ ์ ํ ํด์ ํ๋ก์ ๋น์ ์์ฑํ๋ ๋ฐ, ์ผ๋ฐ์ ์ผ๋ก ํ๊น์ด ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ณ ์๋ ๊ฒฝ์ฐ JDK Proxy์ ๋ฐฉ์์ผ๋ก ํ๋ก์๋ฅผ ์์ฑํด์ฃผ๊ณ ํ๊น์ ๊ฐ์ฒด๊ฐ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ์ง ์์ผ๋ฉด CGLIB ๋ฐฉ์์ผ๋ก ํ๋ก์๊ฐ ์์ฑ๋๋ค.
์ด ํ๋ก์์ ํต์ฌ์ ์ธ ๊ธฐ๋ฅ์ ์ง์ ๋ ๋ฉ์๋๊ฐ ํธ์ถ(Invocation)๋ ๋ ์ด ๋ฉ์๋๋ฅผ ๊ฐ๋ก์ฑ์ด ๋ถ๊ฐ๊ธฐ๋ฅ๋ค์ ์ถ๊ฐํ ์ ์๋๋ก ์ง์ํ๋ ๊ฒ์ด๋ค.
# [ Self-Invocation์ด๋? ]
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted.
target object, ์ฆ AOP๊ฐ ์ ์ฉ๋๋ ๋ฉ์๋๊ฐ ๋์ผํ ํด๋์ค์ ๋ค๋ฅธ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๊ฒ์ self-invocation์ด๋ผ ํ๋ค.
# [ self-invocation ํด๊ฒฐ ๋ฐฉ์ ]
- AopContext
- IoC ์ปจํ ์ด๋ bean ํ์ฉ
- AspectJ Weaving
-> ํ๋ ํด๋น๋ฐฉ๋ฒ๋ค ๋ณด๋ค๋ ํด๋์ค๋ฅผ ๋ถ๋ฆฌํ์ฌ ํธ์ถํ๋ ๊ฒ์ ์งํฅ
# 0125 - GSON Adapter ๋ฑ๋ก
TimeStamp <-> LocalDateTime ์ผ๋ก ์ง๋ ฌํ/์ญ์ง๋ ฌํ ํด์ผ ํ ์ผ์ด ์๊ฒผ๋ค.
# [ Gson registerTypeAdapter ๋ฑ๋ก ]
private final Gson gson = new GsonBuilder().registerTypeAdapter(LocalDateTime.class, new JsonDeserializer<LocalDateTime>() {
@Override
public LocalDateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return LocalDateTime.ofInstant(Instant.parse(json.getAsString()), ZoneOffset.UTC);
}
}).create();
2
3
4
5
6
7
import com.google.gson.*;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
@Slf4j
public class GsonUtils {
private static String PATTERN_DATE = "yyyy-MM-dd";
private static String PATTERN_TIME = "HH:mm:ss";
private static String PATTERN_DATETIME = String.format("%s %s", PATTERN_DATE, PATTERN_TIME);
private static Gson gson = new GsonBuilder()
.disableHtmlEscaping()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.setDateFormat(PATTERN_DATETIME)
.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter().nullSafe())
.registerTypeAdapter(LocalDate.class, new LocalDateAdapter().nullSafe())
.registerTypeAdapter(LocalTime.class, new LocalTimeAdapter().nullSafe())
.create();
public static String toJson(Object o) {
String result = gson.toJson(o);
if("null".equals(result))
return null;
return result;
}
public static <T> T fromJson(String s, Class<T> clazz) {
try {
return gson.fromJson(s, clazz);
} catch(JsonSyntaxException e) {
log.error(e.getMessage());
}
return null;
}
static class LocalDateTimeAdapter extends TypeAdapter<LocalDateTime> {
DateTimeFormatter format = DateTimeFormatter.ofPattern(PATTERN_DATETIME);
@Override
public void write(JsonWriter out, LocalDateTime value) throws IOException {
if(value != null)
out.value(value.format(format));
}
@Override
public LocalDateTime read(JsonReader in) throws IOException {
return LocalDateTime.parse(in.nextString(), format);
}
}
static class LocalDateAdapter extends TypeAdapter<LocalDate> {
DateTimeFormatter format = DateTimeFormatter.ofPattern(PATTERN_DATE);
@Override
public void write(JsonWriter out, LocalDate value) throws IOException {
out.value(value.format(format));
}
@Override
public LocalDate read(JsonReader in) throws IOException {
return LocalDate.parse(in.nextString(), format);
}
}
static class LocalTimeAdapter extends TypeAdapter<LocalTime> {
DateTimeFormatter format = DateTimeFormatter.ofPattern(PATTERN_TIME);
@Override
public void write(JsonWriter out, LocalTime value) throws IOException {
out.value(value.format(format));
}
@Override
public LocalTime read(JsonReader in) throws IOException {
return LocalTime.parse(in.nextString(), format);
}
}
}
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