2021. 8. 13. 08:00ใBack-End ์์ ์ค/Spring Framework
์๋ ํ์ธ์? ์ฃผ๋ํ๋ ์ ๋๋ค.
์ฃผ๋ํ๋์ Spring Boot์ ๋ํด์ ๊ณต๋ถํ๊ณ ์๋ ๊ฒ์ด์์.
์ค๋์ Java Code๋ก ์ง์ Spring Bean ๋ฑ๋กํ๋ ๋ฐฉ๋ฒ์ ๋ํด ๊ณต๋ถ ํด ๋ณด๋๋ก ํ ๊ฒ์ด์์.
๋ฐ๋ก ์์ ํด ๋ณด๊ฒ ์ต๋๋ค!
์ฝ๋์ ๊ด๋ จํ ๋ด์ฉ์ ์ฃผ๋ํ๋์ Github์์ ํ์ธ ํ์ค ์ ์์ต๋๋ค!
๐ ๋ชฉ์ฐจ
01.[Spring Boot] thymeleaf์ Spring Boot
02.[Spring Boot] Spring Web ๊ฐ๋ฐ ๊ธฐ์ด
03.[Spring Boot] ํ์ ๊ด๋ฆฌ ์์ - Backend
04.[Spring Boot] Service ๊ฐ๋ฐ ๋ฐ Test Case ์์ฑ
05.[Spring Boot] Spring Bean๊ณผ ์์กด๊ด๊ณ
06.[Spring Boot] Java Code๋ก ์ง์ Spring Bean ๋ฑ๋ก
07.[Spring Boot] ๋ฑ๋ก, ๋ชฉ๋ก ๋ณด๊ธฐ ๊ตฌํํ๊ธฐ
08.[Spring Boot] ๊ธฐ์กด ์ฝ๋ ์ ์๋๊ณ , ์ค์ ์ผ๋ก ๊ตฌํ Class ๋ณ๊ฒฝ
09.[Spring Boot] ํตํฉ Test
10.[Spring Boot] JPA
11.[Spring Boot] Spring Data JPA
12.[Spring Boot] AOP
๐ Java Code๋ก ์ง์ Spring Bean ๋ฑ๋ก
๋จผ์ ํ์ Service์ ํ์ Repository์ @Service, @Repository, @Autowired๋ฅผ ์ ๊ฑฐํ๊ณ ์คํํ๋ฉด ์ด๋ค ํ์์ด ๋ฐ์ํ ๊น์?
MeberService.java
package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemoryMemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
// ์ปดํฌ๋ํธ ์ค์บ ๋ฐฉ์์ Service
//@Service
public class MemberService { // Service ์ชฝ์ ๋น์ฆ๋์ค ์ฉ์ด์ ๋ง๊ฒ ์ด๋ฆ ๋ฑ์ ์ ์ด์ผ ํ๋ค.
// ์๋ ๋ด์ฉ์์ repository ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ , Service Test์์ ๋ new๋ฅผ ํตํด Repository๋ฅผ ์์ฑํด์ ํ
์คํธํ๋ฉด ์๋ก ๋ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์ด์ฉํ๊ฒ ๋๋ค.
// private final MemoryMemberRepository memberRepository = new MemoryMemberRepository();
// ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ ์๋์ ๊ฐ์ด ์์ฑ์๋ฅผ ํตํด ์ธ๋ถ์์ ์ ๊ทผํ ์ ์๋๋ก ํด ์ค๋ค.
private final MemoryMemberRepository memberRepository;
// @Service๊ฐ ์๋ Service๊ฐ ๊ฐ์ฒด๊ฐ ์์ฑ๋ ๋, @Autowired๊ฐ ๋ถ์ ์์ฑ์๋ ์คํ๋ง์ด ์ปจํ
์ด๋์์ ๋น์ผ๋ก ๊ด๋ฆฌํ ๋, ์์ฑ์๋ฅผ ํธ์ถํ๋๋ฐ, ์ด ๋ MemberService๋ฅผ ๋ฃ์ด์ค๋ค.
// @Autowired
public MemberService(MemoryMemberRepository memberRepository) {
this.memberRepository = memberRepository;
} // ์์ฑ์ ๋
// ํ์ ๊ฐ์
public Long join(Member member) {
// ๊ฐ์ ์ด๋ฆ์ด ์๋ ์ค๋ณต ํ์ ๊ฐ์
๋ฐฉ์ง
// Optional<Member> result = memberRepository.findByName(member.getName());
//
// result.ifPresent(memeber -> { // ifPresent๋ ํด๋น ๊ฐ์ด Null์ด ์๋๊ณ , ์ด๋ค ๊ฐ์ด ์์ผ๋ฉด ๋์ (Option๋ก ๊ฐ์ธ๋ฉด ์ฌ์ฉ ๊ฐ๋ฅ)
// throw new IllegalStateException("์ด๋ฏธ ์กด์ฌํ๋ ํ์ ์
๋๋ค.");
// });
// ์์ ์ฝ๋ ๋ณด๋ค ๋ ์ข์ ์ฝ๋
// memberRepository.findByName(member.getName()).ifPresent(member1 -> {
// throw new IllegalStateException("์ด๋ฏธ ์กด์ฌํ๋ ํ์ ์
๋๋ค.")
// });
// ์์ ์ฝ๋๋ฅผ Methodํ ํ๋ ๊ฒ์ด ์ข๋ค.
// ํด๋น ์ฝ๋๋ฅผ ๋ชจ๋ ์ ํํ๊ณ , Command + Option + M์ ๋๋ฌ์ค๋ค.
validateDuplicationMember(member); // ์ค๋ณต ํ์ ๊ฒ์ฆ
memberRepository.save(member);
return member.getId();
} // join() ๋
private void validateDuplicationMember(Member member) {
// ์์ ์ฝ๋ ๋ณด๋ค ๋ ์ข์ ์ฝ๋
memberRepository.findByName(member.getName()).ifPresent(member1 -> {
throw new IllegalStateException("์ด๋ฏธ ์กด์ฌํ๋ ํ์ ์
๋๋ค.");
});
} // validateDuplicationMember() ๋
public List<Member> findMembers() {
return memberRepository.findAll();
} // findMembers() ๋
public Optional<Member> findOne(Long memberId) {
return memberRepository.findById(memberId);
} // findOne() ๋
} // Class ๋
MemoryMemberRepository.java
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import java.util.*;
//@Repository
public class MemoryMemberRepository implements MemeberRepository{
private static Map<Long, Member> store = new HashMap<>();
private static long sequence = 0L;
@Override
public Member save(Member member) {
member.setId(++sequence);
store.put(member.getId(), member);
return member;
} //save () ๋
@Override
public Optional<Member> findById(Long id) {
return Optional.ofNullable(store.get(id));
} // findById() ๋
@Override
public Optional<Member> findByName(String name) {
return store.values().stream().filter(member -> member.getName().equals(name)).findAny();
} // findByName () ๋
@Override
public List<Member> findAll() {
return new ArrayList<>(store.values());
} // findAll() ๋
// Test๊ฐ ํ๋ ๋๋ ๋๋ง๋ค Repository๋ฅผ Clear ์์ผ์ฃผ๊ธฐ ์ํ ์ฝ๋ (MemoryMemberRepositoryTest์ afterEach()์์ ํธ์ถ)
public void clearStore() {
store.clear();
}
} // Class ๋
๊ธฐ์กด์ ์์ฑํ์๋ Code์์ @Service, @Repository, @Autowired๋ฅผ ์ฃผ์์ฒ๋ฆฌ๋ฅผ ํ๊ณ , ์คํ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ๊ฒ์!
์คํ ๊ฒฐ๊ณผ
/Library/Java/JavaVirtualMachines/jdk-11.0.12.jdk/Contents/Home/bin/java -XX:TieredStopAtLevel=1 -noverify -Dspring.output.ansi.enabled=always -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=57067:/Applications/IntelliJ IDEA.app/Contents/bin -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dfile.encoding=UTF-8 -classpath /Users/juny/SynologyDrive/๊ฐ์ธ์๋ฃ/97.SourceCode/00.Study/00.Inflearn/์คํ๋ง ์
๋ฌธ - ์ฝ๋๋ก ๋ฐฐ์ฐ๋ ์คํ๋ง ๋ถํธ, ์น MVC, DB ์ ๊ทผ ๊ธฐ์ /hello-spring/out/production/classes:/Users/juny/SynologyDrive/๊ฐ์ธ์๋ฃ/97.SourceCode/00.Study/00.Inflearn/์คํ๋ง ์
๋ฌธ - ์ฝ๋๋ก ๋ฐฐ์ฐ๋ ์คํ๋ง ๋ถํธ, ์น MVC, DB ์ ๊ทผ ๊ธฐ์ /hello-spring/out/production/resources:/Users/juny/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-thymeleaf/2.5.3/ac0d6c1779e8a4e77f5be14e38150bf3dd1339fe/spring-boot-starter-thymeleaf-2.5.3.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-web/2.5.3/2cb23f2928177eeb9be81036623f4350a86a433/spring-boot-starter-web-2.5.3.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter/2.5.3/2e16fb3d63961548468a2cd70015d4b1be968fd4/spring-boot-starter-2.5.3.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.thymeleaf/thymeleaf-spring5/3.0.12.RELEASE/aa640b214411978a23cbe271c3fb9569d1bda608/thymeleaf-spring5-3.0.12.RELEASE.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.thymeleaf.extras/thymeleaf-extras-java8time/3.0.4.RELEASE/36e7175ddce36c486fff4578b5af7bb32f54f5df/thymeleaf-extras-java8time-3.0.4.RELEASE.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-json/2.5.3/10336b02e83756f916c0d9510555046cacfc2005/spring-boot-starter-json-2.5.3.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-tomcat/2.5.3/bedcf69b9e83a0744d93e5672320039b55deffd/spring-boot-starter-tomcat-2.5.3.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.springframework/spring-webmvc/5.3.9/c3cd1f0bba2658995e887d2f0011ab9bd3da1773/spring-webmvc-5.3.9.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.springframework/spring-web/5.3.9/88c920ec1bda67fea04daa8e16165777440df473/spring-web-5.3.9.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-autoconfigure/2.5.3/f03d7e9102d93ab25110da850be9facf11818a0b/spring-boot-autoconfigure-2.5.3.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot/2.5.3/e25d2de9e166a8bbbfae633fc03220ab36ac19a9/spring-boot-2.5.3.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-logging/2.5.3/a3a2057be09b4105ecf2e7e3097e0e3fe2eb2684/spring-boot-starter-logging-2.5.3.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/jakarta.annotation/jakarta.annotation-api/1.3.5/59eb84ee0d616332ff44aba065f3888cf002cd2d/jakarta.annotation-api-1.3.5.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.springframework/spring-core/5.3.9/cfef19d1dfa41d56f8de66238dc015334997d573/spring-core-5.3.9.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.yaml/snakeyaml/1.28/7cae037c3014350c923776548e71c9feb7a69259/snakeyaml-1.28.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.thymeleaf/thymeleaf/3.0.12.RELEASE/de1865b0d58590a50c33900115a293335dd8ef25/thymeleaf-3.0.12.RELEASE.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-api/1.7.32/cdcff33940d9f2de763bc41ea05a0be5941176c3/slf4j-api-1.7.32.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.12.4/b1174c05d4ded121a7eaeed3f148709f9585b981/jackson-datatype-jsr310-2.12.4.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.module/jackson-module-parameter-names/2.12.4/87c4e9a3302f0fafe4e5587f9c27d22847d8fe00/jackson-module-parameter-names-2.12.4.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.datatype/jackson-datatype-jdk8/2.12.4/858a1e1b677cbafd3b100d5154f491a7051401c/jackson-datatype-jdk8-2.12.4.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-databind/2.12.4/69206e02e6a696034f06a59d3ddbfbba5a4cd81/jackson-databind-2.12.4.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.apache.tomcat.embed/tomcat-embed-websocket/9.0.50/eb8d0bedeb2a9ed61ea3b3790055e937e52898a3/tomcat-embed-websocket-9.0.50.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.apache.tomcat.embed/tomcat-embed-core/9.0.50/14307c487516ab3526213a1205c5243b0c484e8d/tomcat-embed-core-9.0.50.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.apache.tomcat.embed/tomcat-embed-el/9.0.50/ee4e14e128bf6ffe7650c7a5d8cedf97fb36d91b/tomcat-embed-el-9.0.50.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.springframework/spring-context/5.3.9/887f4579ade4f47cf0102856f4f4c88eda8ec9d7/spring-context-5.3.9.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.springframework/spring-aop/5.3.9/9bcad31a74e60d205500dd67d2220bd0195c63f8/spring-aop-5.3.9.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.springframework/spring-beans/5.3.9/48600db2cb1abc0f7ef2b073f0c1abd78a83bcfc/spring-beans-5.3.9.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.springframework/spring-expression/5.3.9/f5ca763cfb9d62d196efd5d25e8daca7d555ed75/spring-expression-5.3.9.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-classic/1.2.4/f3bc99fd0b226065012b24fe9f808299048bab54/logback-classic-1.2.4.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-to-slf4j/2.14.1/ce8a86a3f50a4304749828ce68e7478cafbc8039/log4j-to-slf4j-2.14.1.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.slf4j/jul-to-slf4j/1.7.32/8a055c04ab44e8e8326901cadf89080721348bdb/jul-to-slf4j-1.7.32.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.springframework/spring-jcl/5.3.9/622eb12c98768b6d3acc71ce06bac8b332607a10/spring-jcl-5.3.9.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.attoparser/attoparser/2.0.5.RELEASE/a93ad36df9560de3a5312c1d14f69d938099fa64/attoparser-2.0.5.RELEASE.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.unbescape/unbescape/1.1.6.RELEASE/7b90360afb2b860e09e8347112800d12c12b2a13/unbescape-1.1.6.RELEASE.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-annotations/2.12.4/752cf9a2562ac2c012e48057e3a4c17dad66c66e/jackson-annotations-2.12.4.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-core/2.12.4/6a1bd259b6c4e3f9219ec8ec0be55ed11eed0c/jackson-core-2.12.4.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-core/1.2.4/5f429ee58dbacf9040f846f1218c36ca6e851596/logback-core-1.2.4.jar:/Users/juny/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-api/2.14.1/cd8858fbbde69f46bce8db1152c18a43328aae78/log4j-api-2.14.1.jar hello.hellospring.HelloSpringApplication
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.5.3)
2021-08-07 03:17:00.400 INFO 1407 --- [ main] h.hellospring.HelloSpringApplication : Starting HelloSpringApplication using Java 11.0.12 on hongsejun-ui-MacBookAir.local with PID 1407 (/Users/juny/SynologyDrive/๊ฐ์ธ์๋ฃ/97.SourceCode/00.Study/00.Inflearn/์คํ๋ง ์
๋ฌธ - ์ฝ๋๋ก ๋ฐฐ์ฐ๋ ์คํ๋ง ๋ถํธ, ์น MVC, DB ์ ๊ทผ ๊ธฐ์ /hello-spring/out/production/classes started by juny in /Users/juny/SynologyDrive/๊ฐ์ธ์๋ฃ/97.SourceCode/00.Study/00.Inflearn/์คํ๋ง ์
๋ฌธ - ์ฝ๋๋ก ๋ฐฐ์ฐ๋ ์คํ๋ง ๋ถํธ, ์น MVC, DB ์ ๊ทผ ๊ธฐ์ /hello-spring)
2021-08-07 03:17:00.406 INFO 1407 --- [ main] h.hellospring.HelloSpringApplication : No active profile set, falling back to default profiles: default
2021-08-07 03:17:01.880 INFO 1407 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2021-08-07 03:17:01.892 INFO 1407 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2021-08-07 03:17:01.892 INFO 1407 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.50]
2021-08-07 03:17:01.976 INFO 1407 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2021-08-07 03:17:01.976 INFO 1407 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1437 ms
2021-08-07 03:17:02.042 WARN 1407 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'memberController' defined in file [/Users/juny/SynologyDrive/๊ฐ์ธ์๋ฃ/97.SourceCode/00.Study/00.Inflearn/์คํ๋ง ์
๋ฌธ - ์ฝ๋๋ก ๋ฐฐ์ฐ๋ ์คํ๋ง ๋ถํธ, ์น MVC, DB ์ ๊ทผ ๊ธฐ์ /hello-spring/out/production/classes/hello/hellospring/controller/MemberController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'hello.hellospring.service.MemberService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
2021-08-07 03:17:02.045 INFO 1407 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2021-08-07 03:17:02.059 INFO 1407 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-08-07 03:17:02.077 ERROR 1407 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in hello.hellospring.controller.MemberController required a bean of type 'hello.hellospring.service.MemberService' that could not be found.
Action:
Consider defining a bean of type 'hello.hellospring.service.MemberService' in your configuration.
์ข
๋ฃ ์ฝ๋ 1(์ผ)๋ก ์๋ฃ๋ ํ๋ก์ธ์ค
Controller์์ MeberService๊ฐ DI๊ฐ ์๋์๋ค๋ณด๋ ์ด๋ ๊ฒ ์ฐพ์ ์ ์๋ค๊ณ ๋์ค๋ ๊ฒ์ด์์.
๋จผ์ ์ฃผ๋ํ๋์ main / java / hello / hellospring / SpringConfig.java ๋ผ๋ Class๋ฅผ ๋ง๋ค ๊ฒ์ด์์.
package hello.hellospring;
import hello.hellospring.repository.MemoryMemberRepository;
import hello.hellospring.service.MemberService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringConfing {
// @Bean : Bean์ ๋ด๊ฐ ์ง์ ๋ง๋ค๊ฒ ๋ค๋ ์๋ฏธ; ์คํ๋ง์ ์ด๊ฒ์ ๋ณด๊ณ , Bean์ ๋ฑ๋กํ๋ผ๋ ๋ช
๋ น์ผ๋ก ์ธ์
@Bean
// ์๋ Method๋ฅผ ํธ์ถํ์ฌ Bean์ ๋ฑ๋ก
public MemberService memberService() {
// MeberService๋ฅผ ์์ฑํ๋ฉด์ memberRepository๋ฅผ Spring Bean์ ๋ฑ๋ก ๋ ์ฃผ์
ํ์ฌ ์ค๋ค.
return new MemberService(memberRepository());
} // memberService() ๋
@Bean
public MemoryMemberRepository memberRepository() {
return new MemoryMemberRepository();
} // memberRepository() ๋
} // Class ๋
์ฐธ๊ณ :
๊ฐ์์์๋ ์๋์ ๊ฐ์ด ์ฝ๋
์๋ ๋ด์ฉ์ฒ๋ผ MemberRepository Method๋ฅผ ์์ฑํ ๋, Interface๋ก ์์ฑํ๊ณ , return๊ฐ์ ๊ตฌํ์ฒด๋ฅผ new๋ก ๋ง๋ค์ด์ ํ๋ ค๊ณ ํ๋ฉด Error ๋ฐ์
package hello.hellospring;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import hello.hellospring.service.MemberService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringConfig {
@Bean
public MemberService memberService() {
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
}
์ด๋ ๊ฒ Error๊ฐ ๋๋ ๊ฒ์ด์์. ์์ ๋ถ๋ถ์ ๋ต์ ์ฐพ์ผ๋ฉด ์๋์ ์ถ๊ฐ๋ก ๋ด์ฉ์ ๋ฌ์ ๋๋๋ก ํ ๊ฒ์!
@Configuration๊ณผ @Bean์ ์ฌ์ฉํ๋ฉด ์ง์ Java Code๋ก Spring Bean์ ์ค์ ํ ์ ์๋ ๊ฒ์ด์์.
Spring Framwork์์ ๋ง์ด ์ฌ์ฉํ๋ ๋ฐฉ์์ผ๋ก XML๋ก๋ ์ค์ ์ ํ ์ ์์ง๋ง, ์ต๊ทผ์๋ ์ ์ฌ์ฉํ์ง ์๊ณ ,
์์ ๋ฐฉ์์ฒ๋ผ Annotaion์ ๋ง์ด ํ์ฉ ํ๋ค๊ณ ํฉ๋๋ค!
DI์๋ Filed, ์์ฑ์, Setter ์ฃผ์ ์ด 3๊ฐ์ง์ ๋ฐฉ๋ฒ์ด ์๋ ๊ฒ์ด์์.
- Filed ์ฃผ์
public class FiledDependencyInjection {
@Autowired Test test;
}
- Setter ์ฃผ์
public class SetterDependencyInjection {
Test test;
public void setTest(Test test) {
this.test = test;
} // setTest() ๋
} // Class ๋
- ์์ฑ์ ์ฃผ์
public class ConstructorDependencyInjection {
Test test;
public ConstructorDependencyInjection(Test test) {
this.test = test;
} // setTest() ๋
} // Class ๋
์์กด ๊ด๊ณ๊ฐ ์คํ์ค์ ๋์ ์ผ๋ก ๋ณํ๋ ๊ฒฝ์ฐ๋ ์์ต๋๋ค!
๊ทธ๋ง์ ๋ฌด์์ด๋๋ฉด Run Time (Web์ด ๋์์ค์ธ ์ํ์์ ์ฃผ์
ํด์ผ ํ ๋ด์ฉ์ด ๋ณ๊ฒฝ๋ ์ผ์ ์๋ค๋ ์๋ฏธ ์
๋๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์์ฑ์ ์ฃผ์ ์ ๊ถ์ฅํ๋ ๊ฒ์ด์์!
์์ฑ์ ์ฃผ์ ์ ์ฒ์ ์คํ ๋จ๊ณ์์๋ง ํธ์ถ์ด ๋์ด ๋์ํ๊ณ , ์ด ํ์๋ ์ ๊ทผํ ์ ์๊ธฐ ๋๋ฌธ์ ๊ทธ๋ ๋ค๊ณ ํฉ๋๋ค!
์์ฆ ์ค๋ฌด์์๋ ์ฃผ๋ก ์ ํํ๋ Controller, Service, Repository ๊ฐ์ ๊ฒ๋ค์ Component Scna์ ์ฌ์ฉํ๋ค๊ณ ํด์!
์ด๋ฏธ ์ฐ๋ฆฌ๊ฐ ํ์ธ ํด ๋ณด์๋ฏ์ด Annotation๋ง ์์ผ๋ฉด ์์์ ํด์ฃผ๋๊น ํธ๋ฆฌํจ ๋๋ฌธ์ด๊ฒ ์ง์?
ํ์ง๋ง, ์ ํํ ๋์ง ์์๊ฑฐ๋, ์ํฉ์ ๋ฐ๋ผ ๊ตฌํ Class๊ฐ ๋ณ๊ฒฝํด์ผ ํ๋ค๋ฉด ์์์ ํ๋ฏ์ด ์ค์ ์ ํตํด Spring Bean์ ๋ฑ๋กํด์ผ ํ๋ ๊ฒ์ด์์.
์ง๊ธ ์ฐ๋ฆฌ๊ฐ ์ด๊ฑธ ๊ณต๋ถํ๋ ๊ฒ์ ์ด ์ค์ต์ด DB๊ฐ ์ ํด์ง์ง ์์ ๊ฐ์์ ์๋๋ฆฌ์ค๋ก ์์๋ก Memory Repository๋ฅผ ์ฌ์ฉ์ค์ธ๋ฐ, ์ด๊ฒ์ ๋ค๋ฅธ Repository๋ก ๋ณ๊ฒฝํ ๊ฒ์ด๊ณ , ์์ ๊ฐ์ด Java Code๋ก Spring Bean์ ์ค์ ํ๋ฉด Service, Repository, Controller๋ฅผ ๊ฑด๋ค์ง ์๊ณ ,
SpringConfig์ Return ๊ฐ์ ์ฝ๊ฐ๋ง ์์ ์ ํด์ฃผ๋ฉด ๋๊ธฐ ๋๋ฌธ์ ๋ฐฐ์ฐ๊ณ ์๋ ๊ฒ์ด์์.
์ฃผ์ํ ์ ์ @Autowired๋ฅผ ํตํ DI๋ Spring์ด ๊ด๋ฆฌํ๋ ๊ฐ์ฒด์์๋ง ๋์์ ํ๋ค๋ ๊ฒ๋๋ค. Spring Bean์ผ๋ก ๋ฑ๋กํ์ง ์๊ณ , ๋ด๊ฐ ์ง์ ์์ฑํ ๊ฐ์ฒด์์๋ ๋์ํ์ง ์๋๋ค๋ ์ ๊ผญ ์์๋ฌ์ผ ํ๋ ๊ฒ์ด์์!
์ฃผ๋ํ๋์ ๊ธ์ด ๋ง์์ ๋์ จ๋์? ๊ตฌ๋ ๊ณผ ๊ณต๊ฐ! ๊ทธ๋ฆฌ๊ณ , ๋๊ธ์ ์ฃผ๋ํ๋์๊ฒ ๋ง์ ํ์ด ๋ฉ๋๋ค
'Back-End ์์ ์ค > Spring Framework' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring Boot] ๊ธฐ์กด ์ฝ๋ ์ ์๋๊ณ , ์ค์ ์ผ๋ก ๊ตฌํ Class ๋ณ๊ฒฝ (0) | 2021.08.15 |
---|---|
[Spring Boot] ๋ฑ๋ก, ๋ชฉ๋ก ๋ณด๊ธฐ ๊ตฌํํ๊ธฐ (0) | 2021.08.14 |
[Spring Boot] Spring Bean๊ณผ ์์กด๊ด๊ณ (0) | 2021.08.12 |
[Spring Boot] Service ๊ฐ๋ฐ ๋ฐ Test Case ์์ฑ (0) | 2021.08.11 |
[Spring Boot] ํ์ ๊ด๋ฆฌ ์์ - Backend (0) | 2021.08.06 |