열심히 끝까지
디바이스 융합 자바(Java) day91(2) - SpringBoot 의존 주입 본문
디바이스 융합 자바(Java) day91(2) - SpringBoot 의존 주입
노유림 2022. 10. 24. 15:37[의존 주입]
> 어떤 객체 A가 뭔가 메서드를 수행할 때,
b.hello() c.hello() 만들어야 함
1) new를 직접 수행해서 바로 사용(== 개발자가 신경써야 함)
>> "강한 결합"이 되어 있다 라고 표현
2) 미리 만들어진 객체를 할당받아서 사용 가능 => DI
: 객체를 생성해주고 라이프사이클(scope)를 관리하고
필요로 하는 곳에 의존을 주입해주는 친구를 == 컨테이너
: IoC(Inversion Of Container)
: IoC를 제공하는 것이 Spring
>> "약한 결합"이 되어 있다 라고 표현
>>> 유지보수가 용이하려면?
== 낮은 결합도, 높은 응집도
>> 예시
package test;
class Member{
String name;
public Member() { // 코드 변화를 주자 문제가 발생하는 코드가 있고 아닌 코드 존재
// private로 바꾸면 강한 결합에서 코드 존재
}
}
public class Test {
public static void createMember1() {
// 강한 결합
Member member1 = new Member();
}
public static void createMember2(Member member) {
// 약한 결합
Member member2 = member;
}
public static void main(String[] args) {
}
}
>> class Member에 public을 private로 바꾸면
강한 결합인 createMember1에서 에러 발생
[의존 주입 방법]
1) .xml << boot에서는 사용 잘 안함
2) 자바 코드 작성
3) @
> 2, 3 사용해볼 것
>>> 자바 코드 작성
>> application 역할을 해줄 친구 생성
@Configuration 작성해줄 것!!
package com.ryo.springboot.test;
import org.springframework.context.annotation.Configuration;
@Configuration // 스프링 컨테이너의 설정 파일 역할
public class Config {
// 설정 파일
}
>> 이 페이지 상황에 @Autowired가 작성되면 빨간줄 날 가능성 존재
>> 그러니 미리 이름 연결해 놓으면 좋겠다...
: 이름 지어놓으면 커스터마이징 가능
package com.ryo.springboot.test;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration // 스프링 컨테이너의 설정 파일 역할
public class Config {
// 설정 파일
@Bean // 객체화 공식(공식 용어가 아님.. 강사님이 제작)
public Leader leaderA() {
// Setter 주입
Leader leader1 = new Leader();
leader1.setName("티모");
leader1.setMember(new MemberA());
return leader1;
}
@Bean(name="ryo") // 이름 생성 가능
public Leader leaderB() {
return new Leader("아리", new MemberA());
}
}
전에 boot 프로젝트 만든 채로 새로 만들면
> 최근(기존의 것) 설정 및 최근 추가한 Dependencies 도 띄움
예시
만든 패키지가 아닌 기존패키지에 TestApplication.java가 존재
>> 이대로 한번 돌려보기
package com.ryo.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
//SpringApplication.run(TestApplication.class, args);
}
}
-----------------
package com.ryo.springboot;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.ryo.springboot.test.Config;
import com.ryo.springboot.test.Leader;
import com.ryo.springboot.test.Member;
// import org.springframework.boot.SpringApplication;
// import org.springframework.boot.autoconfigure.SpringBootApplication;
//@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
//SpringApplication.run(TestApplication.class, args);
// 1. IoC 제공해 줄 스프링 컨테이너 생성하기
ApplicationContext ac = new AnnotationConfigApplicationContext(Config.class);
// Config가 대신하고 있기 때문에 Config.class 보라고 지칭
// 동작 확인한 후 싱글톤으로 객체 생성 및 관리됨
// config.class의 객체를 객체화 진행
// 2. @Bean 등록한 객체 사용해보기
Leader leader1 = (Leader)ac.getBean("leaderA"); // 형변환 가능
leader1.hello();
// leader1 생성 -> config에 있는 bean이 leaderA()인 것을 ac에 넣어 leader1에 저장
// leader의 생성자 hello 가져오기
Leader leader2 = (Leader)ac.getBean("ryo");
leader2.hello();
//
Member member = ac.getBean("memberB", Member.class); // output 타입 지정해서 사용 가능
member.hello("main에서 작성한 안녕하세요");
// 3. 결과 확인
if(leader1 == leader2) {
System.out.println("동일한 객체입니다.");
}else {
System.out.println("동일하지 않은 객체입니다.");
}
}
}
자바 코드 작성 전체 코드-------
Leader.java----------------------
package com.ryo.springboot.test;
public class Leader {
// 외부에서 다이렉트 접근을 막기 위해 private 작성
private String name;
private Member member;
public Leader() {
}
public Leader(String name, Member member) {
this.name = name;
this.member = member;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Member getMember() {
return member;
}
public void setMember(Member member) {
this.member = member;
}
public void hello() {
member.hello(name + ": 안녕하세요!");
}
}
Member.java--------------------
package com.ryo.springboot.test;
public interface Member {
void hello(String msg); // public 앱스트랙 생략
}
MemberA.java------------------
package com.ryo.springboot.test;
public class MemberA implements Member{
@Override
public void hello(String msg) {
System.out.println("A멤버 : " + msg);
}
}
MemberB.java-----------------
package com.ryo.springboot.test;
public class MemberB implements Member{
@Override
public void hello(String msg) {
System.out.println("B멤버 : " + msg);
}
}
Config.java----------------------
package com.ryo.springboot.test;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration // 스프링 컨테이너의 설정 파일 역할
public class Config {
// 설정 파일
@Bean // 객체화 공식(공식 용어가 아님.. 강사님이 제작)
public Leader leaderA() {
// Setter 주입
Leader leader1 = new Leader();
leader1.setName("티모");
leader1.setMember(new MemberA());
return leader1;
}
@Bean(name="ryo")
public Leader leaderB() {
return new Leader("아리", new MemberA());
}
@Bean
public MemberA memberA() {
return new MemberA();
}
@Bean
public MemberB memberB() {
return new MemberB();
}
}
TestApplication-----------------
package com.ryo.springboot;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.ryo.springboot.test.Config;
import com.ryo.springboot.test.Leader;
import com.ryo.springboot.test.Member;
// import org.springframework.boot.SpringApplication;
// import org.springframework.boot.autoconfigure.SpringBootApplication;
//@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
//SpringApplication.run(TestApplication.class, args);
// 1. IoC 제공해 줄 스프링 컨테이너 생성하기
ApplicationContext ac = new AnnotationConfigApplicationContext(Config.class);
// Config가 대신하고 있기 때문에 Config.class 보라고 지칭
// 동작 확인한 후 싱글톤으로 객체 생성 및 관리됨
// config.class의 객체를 객체화 진행
// 2. @Bean 등록한 객체 사용해보기
Leader leader1 = (Leader)ac.getBean("leaderA"); // 형변환 가능
leader1.hello();
// leader1 생성 -> config에 있는 bean이 leaderA()인 것을 ac에 넣어 leader1에 저장
// leader의 생성자 hello 가져오기
Leader leader2 = (Leader)ac.getBean("ryo");
leader2.hello();
//
Member member = ac.getBean("memberB", Member.class); // output 타입 지정해서 사용 가능
member.hello("main에서 작성한 안녕하세요");
// 3. 결과 확인
if(leader1 == leader2) {
System.out.println("동일한 객체입니다.");
}else {
System.out.println("동일하지 않은 객체입니다.");
}
}
}
---------------------------------------------
>>> @
: 위 프로젝트에서 Config 삭제 한 후
@Component와 @Value, @Autowired, @Qualifier 추가
@SpringBootApplication
: Bean(객체)들을 생성할 때, 싱글톤을 유지할 수 있도록 설정 및 관리
: 각각의 객체들이 생성되면 용이한 순간을 추측하여 메모리를 관리
. jar 파일들도 생성 및 설정 관리
: @ 지정된 클래스를 스캔해서 Beam 등록 관리
>> 모든 클래스 파일에 @을 검색해서 Bean 검색
Test02Application.class 에서 SpringBootApplication 실행
1. main 메서드 실행
2. @SpringBootApplication의 영향으로 @ 스캔 및 등록
3. 10번 라인에 의해 내장 톰캣 실행
4. ApplicationContext 생성 == 스프링 컨테이너 실행
-> URL로 요청 시 RequestMapping에 의해 작성한 메서드가 호출되는 방식
@(어노테이션) 전체코드-----------
Leader.java----------------------
package com.ryo.springboot.test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component // Leader 객체화
public class Leader {
// 외부에서 다이렉트 접근을 막기 위해 private 작성
@Value("티모") // setter의 역할을 수행
private String name;
@Autowired
@Qualifier("memberA") //이름으로 볼 수 있도록 설정
private Member member;
public Leader() {
}
public Leader(String name, Member member) {
this.name = name;
this.member = member;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Member getMember() {
return member;
}
public void setMember(Member member) {
this.member = member;
}
public void hello() {
member.hello(name + ": 안녕하세요!");
}
}
MemberA.java-------------------
package com.ryo.springboot.test;
import org.springframework.stereotype.Component;
@Component("memberA")
public class MemberA implements Member{
@Override
public void hello(String msg) {
System.out.println("A멤버 : " + msg);
}
}
MemberB.java-------------------
package com.ryo.springboot.test;
import org.springframework.stereotype.Component;
@Component("memberB")
public class MemberB implements Member{
@Override
public void hello(String msg) {
System.out.println("B멤버 : " + msg);
}
}
TestController.java--------------
package com.ryo.springboot.test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class TestController {
@Autowired
Leader leader1;
@Autowired
Leader leader2;
@Autowired
@Qualifier("memberB")
Member member;
@RequestMapping("/")
public @ResponseBody String root() { // 이 글자가 @ResponseBody를 통해 화면에 출력
leader1.hello();
leader1.setMember(member);
leader1.hello();
if(leader1 == leader2) {
System.out.println("동일한 객체입니다.");
}else {
System.out.println("동일하지 않은 객체입니다.");
}
return "루트(표지) 페이지";
}
}
Test02Application.java---------
package com.ryo.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Test02Application {
public static void main(String[] args) {
SpringApplication.run(Test02Application.class, args); // 내장된 Tomcat 실행
// Test02Application.class 에서 SpringBootApplication 실행
// 1. main 메서드 실행
// 2. @SpringBootApplication의 영향으로 @ 스캔 및 등록
// 3. 10번 라인에 의해 내장 톰캣 실행
// 4. ApplicationContext 생성 == 스프링 컨테이너 실행
// -> URL로 요청 시 RequestMapping에 의해 작성한 메서드가 호출되는 방식
}
}
----------------------------------------------
[Tip 구간]
Tip1 @Override는..?
Override는 컴파일러에게 정보를 제공
@Bean에서 이름 비교 시 필요한 것
Autowired는
Anotation는
Qualifier는
> @Override를 작성하지 않으면 상위 클래스 바로 접근은 힘들겠지만
그럼에도 오버라이드 된 상태
: 개발 용이성을 표현해주는 것(오버라이드 된 것이라는 언급이 없으면 유지보수 힘듬)
> 회사에서는 @도 작성해서 쓸 가능성 존재
Tip2 ApplicationContext ac = new AnnotaionConfigApplicationContext(?);
=> 디자인 패턴 중 하나의 예시
'디바이스 융합 자바(Java)기반 풀스택 개발자 양성과정(수업내용)' 카테고리의 다른 글
디바이스 융합 자바(Java) day93 - Spring Boot : Validator(유효성 검사) (0) | 2022.10.26 |
---|---|
디바이스 융합 자바(Java) day92 - Spring Boot 설정[MVC 패턴] (0) | 2022.10.25 |
디바이스 융합 자바(Java) day91(1) - SpringBoot 설치 및 설정 (0) | 2022.10.24 |
디바이스 융합 자바(Java) day80 - 셀레니움 크롤링 혼자 공부한 것 (0) | 2022.10.06 |
디바이스 융합 자바(Java) day79 - Mybatis 프레임워크를 Spring에 연동 (0) | 2022.10.05 |