-
Notifications
You must be signed in to change notification settings - Fork 379
[JDBC 라이브러리 구현하기 - 1, 2단계] 현구막(최현구) 미션 제출합니다. #34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
22072d5
d9cfaa1
6d62613
80140bd
c158788
2d3fb19
91695f5
acf57da
d9225b1
54898b1
8fab7ae
4e4415a
4b17405
308315d
dbf9765
1f0c15d
37087bf
832fb74
e85d4d8
85c9ffa
a6111c0
f1b96c1
e0e3b96
86eb046
9cb151c
a7fa076
7defbd9
92a2d11
ced9630
4d36e3e
5d1022d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,21 @@ | ||
| package com.techcourse.config; | ||
|
|
||
| import javax.sql.DataSource; | ||
| import nextstep.web.annotation.Configuration; | ||
| import nextstep.web.annotation.Initialize; | ||
| import org.h2.jdbcx.JdbcDataSource; | ||
|
|
||
| import java.util.Objects; | ||
|
|
||
| @Configuration | ||
| public class DataSourceConfig { | ||
|
|
||
| private static javax.sql.DataSource INSTANCE; | ||
| private static DataSource INSTANCE; | ||
|
|
||
| public static javax.sql.DataSource getInstance() { | ||
| private DataSourceConfig() {} | ||
|
|
||
| @Initialize | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저는 단순히
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| public static DataSource getInstance() { | ||
| if (Objects.isNull(INSTANCE)) { | ||
| INSTANCE = createJdbcDataSource(); | ||
| } | ||
|
|
@@ -22,6 +29,4 @@ private static JdbcDataSource createJdbcDataSource() { | |
| jdbcDataSource.setPassword(""); | ||
| return jdbcDataSource; | ||
| } | ||
|
|
||
| private DataSourceConfig() {} | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,18 @@ | ||
| package nextstep.web; | ||
|
|
||
| import java.lang.reflect.Field; | ||
| import java.lang.reflect.Constructor; | ||
| import java.lang.reflect.Method; | ||
| import java.util.Arrays; | ||
| import java.util.HashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Set; | ||
| import javax.sql.DataSource; | ||
| import java.util.stream.Collectors; | ||
| import nextstep.mvc.exception.ComponentContainerException; | ||
| import nextstep.web.annotation.Autowired; | ||
| import nextstep.web.annotation.Configuration; | ||
| import nextstep.web.annotation.Controller; | ||
| import nextstep.web.annotation.Initialize; | ||
| import nextstep.web.annotation.Repository; | ||
| import nextstep.web.annotation.Service; | ||
| import org.reflections.Reflections; | ||
|
|
@@ -17,39 +23,58 @@ public class ComponentContainer { | |
|
|
||
| private ComponentContainer() {} | ||
|
|
||
| public static void initialize(DataSource dataSource, Object... basePackage) throws Exception { | ||
| public static void initialize(Object... basePackage) throws Exception { | ||
| Reflections reflections = new Reflections(basePackage); | ||
| initializeRepositories(reflections.getTypesAnnotatedWith(Repository.class), dataSource); | ||
| initializeConfigurations(reflections.getTypesAnnotatedWith(Configuration.class)); | ||
| initializeComponents(reflections.getTypesAnnotatedWith(Repository.class)); | ||
| initializeComponents(reflections.getTypesAnnotatedWith(Service.class)); | ||
| initializeComponents(reflections.getTypesAnnotatedWith(Controller.class)); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 그럴 일이 있을지는 모르겠지만 새로운 애너테이션이 생성된다면 계속해서 한 줄 한 줄 코드가 추가될 것 같아요. for (Class<? extends Annotation> clazz : ANNOTATION_COMPONENTS) {
initializeComponents(reflections.getTypesAnnotatedWith(clazz));
}There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아마도 이 코드는
라던 현구막의 생각이 반영된 코드가 아닌가 싶어서 나중에는 이렇게 바뀔 수도 있겠네요~ 라고 언급하고 넘어가는 정도로 할게요 😉😃
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 리스트는 순서를 보장할 수 있으니 충분히 가능하겠네요!!!
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 말씀해주신대로 상수로 관리하려하다가, 당장은 사용하는 곳이 한 곳 뿐이라 지역변수로 두었습니다! public static void initialize(Object... basePackage) throws Exception {
Reflections reflections = new Reflections(basePackage);
initializeConfigurations(reflections.getTypesAnnotatedWith(Configuration.class));
List<Class<? extends Annotation>> annotations = List.of(Repository.class, Service.class, Controller.class);
for (Class<? extends Annotation> annotation : annotations) {
initializeComponents(reflections.getTypesAnnotatedWith(annotation));
}
} |
||
| } | ||
|
|
||
| private static void initializeRepositories(Set<Class<?>> repositoryTypes, DataSource dataSource) throws Exception { | ||
| for (Class<?> repository : repositoryTypes) { | ||
| Object instance = repository.getConstructor(DataSource.class).newInstance(dataSource); | ||
| COMPONENTS.put(repository, instance); | ||
| private static void initializeConfigurations(Set<Class<?>> configurationTypes) throws Exception { | ||
| for (Class<?> configuration : configurationTypes) { | ||
| List<Method> initializeMethods = Arrays.stream(configuration.getMethods()) | ||
| .filter(method -> method.isAnnotationPresent(Initialize.class)) | ||
| .collect(Collectors.toList()); | ||
|
|
||
| Constructor<?> constructor = configuration.getDeclaredConstructor(); | ||
| constructor.setAccessible(true); | ||
| initializeConfigurationMethods(constructor.newInstance(), initializeMethods); | ||
| } | ||
| } | ||
|
|
||
| private static void initializeConfigurationMethods(Object instance, List<Method> initializeMethods) throws Exception { | ||
| for (Method method : initializeMethods) { | ||
| COMPONENTS.put(method.getReturnType(), method.invoke(instance)); | ||
| } | ||
| } | ||
|
|
||
| private static void initializeComponents(Set<Class<?>> componentTypes) throws Exception { | ||
| for (Class<?> type : componentTypes) { | ||
| Class<?>[] fieldTypes = getFieldTypes(type); | ||
| Object[] fieldObjects = getFieldObjects(fieldTypes); | ||
| Constructor<?> constructor = getConstructor(type); | ||
| Object[] parameterObjects = getConstructorParameterObjects(constructor); | ||
|
|
||
| Object instance = type.getConstructor(fieldTypes).newInstance(fieldObjects); | ||
| COMPONENTS.put(type, instance); | ||
| COMPONENTS.put(type, constructor.newInstance(parameterObjects)); | ||
| } | ||
| } | ||
|
|
||
| private static Class<?>[] getFieldTypes(Class<?> classTypes) { | ||
| return Arrays.stream(classTypes.getDeclaredFields()) | ||
| .map(Field::getType) | ||
| .filter(COMPONENTS::containsKey) | ||
| .toArray(Class<?>[]::new); | ||
| private static Constructor<?> getConstructor(Class<?> type) { | ||
| return Arrays.stream(type.getConstructors()) | ||
| .filter(constructor -> constructor.isAnnotationPresent(Autowired.class)) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이런식으로 빈들을 주입해줄 (특정한) 생성자를 지정하고 그 생성자들에 빈을 주입하는거군요 ? 🤔 |
||
| .findAny() | ||
| .orElseGet(() -> getDefaultConstructor(type)); | ||
| } | ||
|
|
||
| private static Constructor<?> getDefaultConstructor(Class<?> type) { | ||
| try { | ||
| return type.getDeclaredConstructor(); | ||
| } catch (NoSuchMethodException e) { | ||
| throw new ComponentContainerException("기본 생성자 탐색에 실패했습니다."); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 우와... 👍 이 예외는 진짜 현구막의 꼼꼼함이 느껴지네요 😧 |
||
| } | ||
| } | ||
|
|
||
| private static Object[] getFieldObjects(Class<?>[] fieldTypes) { | ||
| return Arrays.stream(fieldTypes) | ||
| private static Object[] getConstructorParameterObjects(Constructor<?> constructor) { | ||
| return Arrays.stream(constructor.getParameterTypes()) | ||
| .map(COMPONENTS::get) | ||
| .toArray(Object[]::new); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package nextstep.web.annotation; | ||
|
|
||
| import java.lang.annotation.ElementType; | ||
| import java.lang.annotation.Retention; | ||
| import java.lang.annotation.RetentionPolicy; | ||
| import java.lang.annotation.Target; | ||
|
|
||
| @Target(ElementType.CONSTRUCTOR) | ||
| @Retention(RetentionPolicy.RUNTIME) | ||
| public @interface Autowired { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package nextstep.web.annotation; | ||
|
|
||
| import java.lang.annotation.ElementType; | ||
| import java.lang.annotation.Retention; | ||
| import java.lang.annotation.RetentionPolicy; | ||
| import java.lang.annotation.Target; | ||
|
|
||
| @Target({ElementType.TYPE}) | ||
| @Retention(RetentionPolicy.RUNTIME) | ||
| public @interface Configuration { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package nextstep.web.annotation; | ||
|
|
||
| import java.lang.annotation.ElementType; | ||
| import java.lang.annotation.Retention; | ||
| import java.lang.annotation.RetentionPolicy; | ||
| import java.lang.annotation.Target; | ||
|
|
||
| @Target({ElementType.METHOD}) | ||
| @Retention(RetentionPolicy.RUNTIME) | ||
| public @interface Initialize { | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 클래스에 불필요한 import 문들이 있는데 제거하면 좋을 것 같아요 👀
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
앗... 꼼꼼한 리뷰 감사합니다 ㅠㅠ 요즘 120자 제한을 두고도 가독성을 위해 조금씩 넘겨서 코드를 짜다보니
코드 리포맷팅을 사용하면 코드 라인이 넘어가는게 싫어서 리포맷팅을 잘 안누르게 되네요.. 이상한 버릇이 생겨버렸어요..
넘길 땐 넘길 줄 알아야 하는데!!!!!