From 55e83c05b101ca3d929745a1f41e170119708a85 Mon Sep 17 00:00:00 2001 From: JaehongDev Date: Thu, 20 Apr 2023 15:35:25 +0900 Subject: [PATCH] =?UTF-8?q?feature:=203=EC=A3=BC=EC=B0=A8=20=ED=95=99?= =?UTF-8?q?=EC=8A=B5=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jaehong/helloboot/build.gradle | 1 + .../example/helloboot/HelloController.java | 7 +++ .../com/example/helloboot/HelloDecorator.java | 20 +++++++ .../helloboot/HellobootApplication.java | 21 +------ .../example/helloboot/SimpleHelloService.java | 8 ++- .../config/EnableMyAutoConfiguration.java | 14 +++++ .../config/MyAutoConfigImportSelector.java | 23 ++++++++ .../main/java/config/MyAutoConfiguration.java | 14 +++++ .../java/config/MySpringBootApplication.java | 17 ++++++ .../autoconfig/DispatcherServletConfig.java | 14 +++++ .../JettyServletWebServerConfig.java | 15 +++++ .../TomcatServletWebServerConfig.java | 15 +++++ .../config.MyAutoConfiguration.imports | 2 + .../com/example/helloboot/HelloApiTest.java | 30 ++++++++++ .../helloboot/HelloControllerTest.java | 27 +++++++++ .../example/helloboot/HelloServiceTest.java | 16 ++++++ .../helloboot/HellobootApplicationTests.java | 13 ----- .../test/java/study/ConfigurationTest.java | 55 +++++++++++++++++++ 18 files changed, 279 insertions(+), 33 deletions(-) create mode 100644 jaehong/helloboot/src/main/java/com/example/helloboot/HelloDecorator.java create mode 100644 jaehong/helloboot/src/main/java/config/EnableMyAutoConfiguration.java create mode 100644 jaehong/helloboot/src/main/java/config/MyAutoConfigImportSelector.java create mode 100644 jaehong/helloboot/src/main/java/config/MyAutoConfiguration.java create mode 100644 jaehong/helloboot/src/main/java/config/MySpringBootApplication.java create mode 100644 jaehong/helloboot/src/main/java/config/autoconfig/DispatcherServletConfig.java create mode 100644 jaehong/helloboot/src/main/java/config/autoconfig/JettyServletWebServerConfig.java create mode 100644 jaehong/helloboot/src/main/java/config/autoconfig/TomcatServletWebServerConfig.java create mode 100644 jaehong/helloboot/src/main/resources/META-INF.spring/config.MyAutoConfiguration.imports create mode 100644 jaehong/helloboot/src/test/java/com/example/helloboot/HelloApiTest.java create mode 100644 jaehong/helloboot/src/test/java/com/example/helloboot/HelloControllerTest.java create mode 100644 jaehong/helloboot/src/test/java/com/example/helloboot/HelloServiceTest.java delete mode 100644 jaehong/helloboot/src/test/java/com/example/helloboot/HellobootApplicationTests.java create mode 100644 jaehong/helloboot/src/test/java/study/ConfigurationTest.java diff --git a/jaehong/helloboot/build.gradle b/jaehong/helloboot/build.gradle index c2649a6..658d4ae 100644 --- a/jaehong/helloboot/build.gradle +++ b/jaehong/helloboot/build.gradle @@ -14,6 +14,7 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-jetty' testImplementation 'org.springframework.boot:spring-boot-starter-test' } diff --git a/jaehong/helloboot/src/main/java/com/example/helloboot/HelloController.java b/jaehong/helloboot/src/main/java/com/example/helloboot/HelloController.java index 8be6a1c..7f92f63 100644 --- a/jaehong/helloboot/src/main/java/com/example/helloboot/HelloController.java +++ b/jaehong/helloboot/src/main/java/com/example/helloboot/HelloController.java @@ -1,6 +1,8 @@ package com.example.helloboot; +import java.util.LinkedList; +import java.util.Queue; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -8,6 +10,7 @@ public class HelloController { private final HelloService helloService; + public HelloController(HelloService helloService) { this.helloService = helloService; } @@ -15,6 +18,10 @@ public HelloController(HelloService helloService) { @RequestMapping("/hello") public String hello(String name) { + Queue queue = new LinkedList<>(); + if (name == null || name.trim().length() == 0) { + throw new IllegalArgumentException(); + } return helloService.sayHello(name); } } diff --git a/jaehong/helloboot/src/main/java/com/example/helloboot/HelloDecorator.java b/jaehong/helloboot/src/main/java/com/example/helloboot/HelloDecorator.java new file mode 100644 index 0000000..8bcc0a3 --- /dev/null +++ b/jaehong/helloboot/src/main/java/com/example/helloboot/HelloDecorator.java @@ -0,0 +1,20 @@ +package com.example.helloboot; + + +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; + +@Service +@Primary +public class HelloDecorator implements HelloService { + private final HelloService helloService; + + public HelloDecorator(HelloService helloService) { + this.helloService = helloService; + } + + @Override + public String sayHello(String name) { + return "*" + helloService.sayHello(name) + "*"; + } +} diff --git a/jaehong/helloboot/src/main/java/com/example/helloboot/HellobootApplication.java b/jaehong/helloboot/src/main/java/com/example/helloboot/HellobootApplication.java index 65581f6..8618431 100644 --- a/jaehong/helloboot/src/main/java/com/example/helloboot/HellobootApplication.java +++ b/jaehong/helloboot/src/main/java/com/example/helloboot/HellobootApplication.java @@ -1,30 +1,15 @@ package com.example.helloboot; +import config.MySpringBootApplication; import org.springframework.boot.SpringApplication; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.DispatcherServlet; - -@Configuration -@ComponentScan +@MySpringBootApplication public class HellobootApplication { - @Bean - public ServletWebServerFactory servletWebServerFactory(){ - return new TomcatServletWebServerFactory(); - } - - @Bean - public DispatcherServlet dispatcherServlet(){ - return new DispatcherServlet(); - } public static void main(String[] args) { SpringApplication.run(HellobootApplication.class, args); } + } diff --git a/jaehong/helloboot/src/main/java/com/example/helloboot/SimpleHelloService.java b/jaehong/helloboot/src/main/java/com/example/helloboot/SimpleHelloService.java index eb9b12f..0ff0648 100644 --- a/jaehong/helloboot/src/main/java/com/example/helloboot/SimpleHelloService.java +++ b/jaehong/helloboot/src/main/java/com/example/helloboot/SimpleHelloService.java @@ -1,8 +1,12 @@ package com.example.helloboot; -public class SimpleHelloService implements HelloService{ + +import org.springframework.stereotype.Service; + +@Service +public class SimpleHelloService implements HelloService { @Override public String sayHello(String name) { - return "hello "+ name; + return "hello " + name; } } diff --git a/jaehong/helloboot/src/main/java/config/EnableMyAutoConfiguration.java b/jaehong/helloboot/src/main/java/config/EnableMyAutoConfiguration.java new file mode 100644 index 0000000..2876d57 --- /dev/null +++ b/jaehong/helloboot/src/main/java/config/EnableMyAutoConfiguration.java @@ -0,0 +1,14 @@ +package config; + + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.springframework.context.annotation.Import; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Import(MyAutoConfigImportSelector.class) +public @interface EnableMyAutoConfiguration { +} diff --git a/jaehong/helloboot/src/main/java/config/MyAutoConfigImportSelector.java b/jaehong/helloboot/src/main/java/config/MyAutoConfigImportSelector.java new file mode 100644 index 0000000..b362722 --- /dev/null +++ b/jaehong/helloboot/src/main/java/config/MyAutoConfigImportSelector.java @@ -0,0 +1,23 @@ +package config; + +import java.util.ArrayList; +import org.springframework.boot.context.annotation.ImportCandidates; +import org.springframework.context.annotation.DeferredImportSelector; +import org.springframework.core.type.AnnotationMetadata; + +public class MyAutoConfigImportSelector implements DeferredImportSelector { + private final ClassLoader classLoader; + + public MyAutoConfigImportSelector(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + @Override + public String[] selectImports(AnnotationMetadata importingClassMetadata) { + var autoConfigs = new ArrayList(); + ImportCandidates.load(MyAutoConfigImportSelector.class, classLoader).forEach(autoConfigs::add); + + //ImportCandidates.load(MyAutoConfiguration.class, classLoader).forEach(autoConfigs::add); + return autoConfigs.toArray(String[]::new); + } +} diff --git a/jaehong/helloboot/src/main/java/config/MyAutoConfiguration.java b/jaehong/helloboot/src/main/java/config/MyAutoConfiguration.java new file mode 100644 index 0000000..09931c2 --- /dev/null +++ b/jaehong/helloboot/src/main/java/config/MyAutoConfiguration.java @@ -0,0 +1,14 @@ +package config; + + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.springframework.context.annotation.Configuration; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Configuration(proxyBeanMethods = false) +public @interface MyAutoConfiguration { +} diff --git a/jaehong/helloboot/src/main/java/config/MySpringBootApplication.java b/jaehong/helloboot/src/main/java/config/MySpringBootApplication.java new file mode 100644 index 0000000..03c7ee2 --- /dev/null +++ b/jaehong/helloboot/src/main/java/config/MySpringBootApplication.java @@ -0,0 +1,17 @@ +package config; + + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +@Configuration +@ComponentScan +@EnableMyAutoConfiguration +public @interface MySpringBootApplication { +} diff --git a/jaehong/helloboot/src/main/java/config/autoconfig/DispatcherServletConfig.java b/jaehong/helloboot/src/main/java/config/autoconfig/DispatcherServletConfig.java new file mode 100644 index 0000000..09adfc3 --- /dev/null +++ b/jaehong/helloboot/src/main/java/config/autoconfig/DispatcherServletConfig.java @@ -0,0 +1,14 @@ +package config.autoconfig; + + +import config.MyAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.web.servlet.DispatcherServlet; + +@MyAutoConfiguration +public class DispatcherServletConfig { + @Bean + public DispatcherServlet dispatcherServlet() { + return new DispatcherServlet(); + } +} diff --git a/jaehong/helloboot/src/main/java/config/autoconfig/JettyServletWebServerConfig.java b/jaehong/helloboot/src/main/java/config/autoconfig/JettyServletWebServerConfig.java new file mode 100644 index 0000000..d1dd576 --- /dev/null +++ b/jaehong/helloboot/src/main/java/config/autoconfig/JettyServletWebServerConfig.java @@ -0,0 +1,15 @@ +package config.autoconfig; + + +import config.MyAutoConfiguration; +import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; +import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.context.annotation.Bean; + +@MyAutoConfiguration +public class JettyServletWebServerConfig { + @Bean + public ServletWebServerFactory servletWebServerFactory() { + return new JettyServletWebServerFactory(); + } +} diff --git a/jaehong/helloboot/src/main/java/config/autoconfig/TomcatServletWebServerConfig.java b/jaehong/helloboot/src/main/java/config/autoconfig/TomcatServletWebServerConfig.java new file mode 100644 index 0000000..6564e9c --- /dev/null +++ b/jaehong/helloboot/src/main/java/config/autoconfig/TomcatServletWebServerConfig.java @@ -0,0 +1,15 @@ +package config.autoconfig; + +import config.MyAutoConfiguration; +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.context.annotation.Bean; + +@MyAutoConfiguration +public class TomcatServletWebServerConfig { + @Bean + public ServletWebServerFactory servletWebServerFactory() { + return new TomcatServletWebServerFactory(); + } + +} diff --git a/jaehong/helloboot/src/main/resources/META-INF.spring/config.MyAutoConfiguration.imports b/jaehong/helloboot/src/main/resources/META-INF.spring/config.MyAutoConfiguration.imports new file mode 100644 index 0000000..d69448f --- /dev/null +++ b/jaehong/helloboot/src/main/resources/META-INF.spring/config.MyAutoConfiguration.imports @@ -0,0 +1,2 @@ +config.autoconfig.TomcatServletWebServerConfig +config.autoconfig.DispatcherServletConfig \ No newline at end of file diff --git a/jaehong/helloboot/src/test/java/com/example/helloboot/HelloApiTest.java b/jaehong/helloboot/src/test/java/com/example/helloboot/HelloApiTest.java new file mode 100644 index 0000000..080abc9 --- /dev/null +++ b/jaehong/helloboot/src/test/java/com/example/helloboot/HelloApiTest.java @@ -0,0 +1,30 @@ +package com.example.helloboot; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.http.MediaType.TEXT_PLAIN_VALUE; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; + +class HelloApiTest { + + @Test + void hello_test() { + final var rest = new TestRestTemplate(); + final var response = rest.getForEntity("http://localhost:8080/hello?name={name}", String.class, "Spring"); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(response.getBody()).isEqualTo("*hello Spring*"); + assertThat(response.getHeaders().getFirst(HttpHeaders.CONTENT_TYPE)).startsWith(TEXT_PLAIN_VALUE); + } + + @Test + void fail_test() { + final var rest = new TestRestTemplate(); + final var response = rest.getForEntity("http://localhost:8080/hello?name=", String.class); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); + } +} \ No newline at end of file diff --git a/jaehong/helloboot/src/test/java/com/example/helloboot/HelloControllerTest.java b/jaehong/helloboot/src/test/java/com/example/helloboot/HelloControllerTest.java new file mode 100644 index 0000000..6a5c86d --- /dev/null +++ b/jaehong/helloboot/src/test/java/com/example/helloboot/HelloControllerTest.java @@ -0,0 +1,27 @@ +package com.example.helloboot; + +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + + +class HelloControllerTest { + + + @Test + void success_test() { + final var helloController = new HelloController(name -> name); + final var result = helloController.hello("spring"); + + Assertions.assertThat(result).isEqualTo("spring"); + } + + @Test + void fail_test() { + final var helloController = new HelloController(name -> null); + + assertThatIllegalArgumentException().isThrownBy(() -> helloController.hello(null)); + assertThatIllegalArgumentException().isThrownBy(() -> helloController.hello("")); + } +} \ No newline at end of file diff --git a/jaehong/helloboot/src/test/java/com/example/helloboot/HelloServiceTest.java b/jaehong/helloboot/src/test/java/com/example/helloboot/HelloServiceTest.java new file mode 100644 index 0000000..b44ba82 --- /dev/null +++ b/jaehong/helloboot/src/test/java/com/example/helloboot/HelloServiceTest.java @@ -0,0 +1,16 @@ +package com.example.helloboot; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +class HelloServiceTest { + + + @Test + void success_test() { + final var sampleHello = new SimpleHelloService(); + final var result = sampleHello.sayHello("name"); + + Assertions.assertThat(result).isEqualTo("hello name"); + } +} \ No newline at end of file diff --git a/jaehong/helloboot/src/test/java/com/example/helloboot/HellobootApplicationTests.java b/jaehong/helloboot/src/test/java/com/example/helloboot/HellobootApplicationTests.java deleted file mode 100644 index 6d5581c..0000000 --- a/jaehong/helloboot/src/test/java/com/example/helloboot/HellobootApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.helloboot; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class HellobootApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/jaehong/helloboot/src/test/java/study/ConfigurationTest.java b/jaehong/helloboot/src/test/java/study/ConfigurationTest.java new file mode 100644 index 0000000..1b5407b --- /dev/null +++ b/jaehong/helloboot/src/test/java/study/ConfigurationTest.java @@ -0,0 +1,55 @@ +package study; + +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +public class ConfigurationTest { + + @Test + void configuration() { + + } + + @Configuration + static class MyConfig { + @Bean + Common common() { + return new Common(); + } + + @Bean + Bean1 bean1() { + return new Bean1(common()); + } + + @Bean + Bean2 bean2() { + return new Bean2(common()); + } + } + + static class Bean2 { + private final Common common; + + Bean2(Common common) { + this.common = common; + } + } + + static class Bean1 { + private final Common common; + + Bean1(Common common) { + this.common = common; + } + } + + static class Common { + + } + // bean1 <-- common + // bean2 <-- common + // 스프링은 스프링컨테이너에 의해서 모든 빈들은 싱글턴으로 관리 되어지기 때문에 bean1과 bean2는 모두 동일한 common을 주입받습니다. + +}