본문 바로가기
Spring

[Spring] 05. 어노테이션 의존성 주입

by ssunooo 2024. 10. 4.

 

 

의존성 주입의 방법

 

1. bean

  • .xml(설정파일) 내에서 객체 생성
  • 문제점 : 객체가 많아지면 설정파일의 가독성 하락
  • 해결책 : 어노테이션 사용

 

2. 어노테이션 (@, 애너테이션)

  • 클래스에서 bean 등록
  • 응집도 향상, 가독성 증가
  • 컴파일 하기 전에 작동

 

 

어노테이션 의존성 주입

 

1. 스키마 추가

 

xmlns:context=http://www.springframework.org/schema/context 추가


xsi:schemaLocation에서
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd 를 추가

 

<스키마 추가 완료 코드>

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
                  http://www.springframework.org/schema/beans/spring-beans.xsd
                  http://www.springframework.org/schema/context
                  http://www.springframework.org/schema/context/spring-context-4.2.xsd">



2. component 범위 설정

 

</context:component-scan base-package="패키지명" > 스캔하는 범위 추가 코드

<context:component-scan base-package="test" />

 

 

3. 어노테이션 사용


@Component : <bean>의 역할

  • 컴포넌트 == Bean == 모듈 == 패키지 == 위젯 : 넓은 의미의 리팩토링
  • 함수화 == 메서드화 : 좁은 의미의 리팩토링

@Autowired : 의존주입(DI) 대상 설정 (자료형만으로)

  • 같은 자료형이 두개 이상 있을 때 오류 (의존성 주입 모호성 오류)

※ 1:1 어노테이션 하나 당 멤버변수 하나

 

@Qualifier : id를 명시해주는 어노테이션

  • 의존성 주입 모호성 오류 해결

 

.xml 에서 <bean> 변경 = 컴파일x = 비용 x
클래스에서 어노테이션 변경 = 컴파일o = 비용o

 

실습

 

<applicationContext.xml = 설정파일>

<?xml version="1.0" encoding="UTF-8"?>             
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
                  http://www.springframework.org/schema/beans/spring-beans.xsd
                  http://www.springframework.org/schema/context
                  http://www.springframework.org/schema/context/spring-context-4.2.xsd">
                  
   <context:component-scan base-package="test" />
   
   <bean class="test.AppleWatch" id="aw"></bean>
   <bean class="test.GalaxyWatch" id="sw"></bean>
    
</beans>

 


<Client.java>

package test;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class Client {
	public static void main(String[] args) {
		
		// 스프링 컨테이너 생성, 컨테이너를 구동시키는 코드
		AbstractApplicationContext factory = new GenericXmlApplicationContext("applicationContext.xml");
		// Phone phone = factory야.폰객체좀("아이폰");
		// 다운캐스팅 (Phone)으로 해줘야한다
		// 다운 캐스팅 - 상위객체를 하위객체로 변환
		Phone phone1 = (Phone)factory.getBean("apple");
		Phone phone2 = (Phone)factory.getBean("samsung");
		// Bean == 자바객체 == 객체 == POJO
		// 객체를 요청하다.
		// == look up
		
		phone1.powerOn();
		phone2.powerOn();
		phone1.powerOff();
		phone2.powerOff();
		
		/*
		// new를 1번만 했기때문에 모두 공유
		// "싱글톤" 패턴이 유지된다 == 어떠한 객체가 메모리에 하나만 있다.
		// 결론) 스프링 프레임워크(컨테이너)는 싱글톤 패턴을 유지시킴
		// scope="prototype"의 bean설정을 통해 여러객체를 메모리에 저장 가능
		
		
		factory.close();
		
		// 결합도가 높은 프로젝트의 형태 >> 유지보수 어려움
		// 결합도를 낮추기 위한 방법들
		// 1. 오버로딩 vs [오버라이딩] == 오버라이딩을 강제해야한다 == Interface 사용
		// 		함수명 중복정의 허용
		// 		메서드 시그니쳐가 다르면
		// 		함수명이 같아도 된다!
		//		상속 관계와 무간
		// 			메서드 재정의
		// 			메서드 시그니쳐가 같아야함
		// 			상속관계 O
		
		// 2. 개발 패턴 활용하기
		// 		팩토리 패턴
		// 		ㅇㅇ객체가 필요해. 하고 부탁하면,
		// 		해당 객체를 주는 패턴을 의미함
		// 		ex) HandlerMapper
	}
}

 


<ApplePhone.java>

package test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component("apple")
public class ApplePhone implements Phone {
	@Autowired // 메모리의 자료형(타입)을 인지해서 주입해줌
	@Qualifier("aw")
	private Watch watch; // 멤버변수 초기화 = 생성자 // 워치에 의존성 주입을 해야한다. // DI 대상
	
//	private int num;
	
	public ApplePhone() {
//		this.watch = new AppleWatch();  // 개발자가 new를 직접 사용하기 때문에 사용x
		System.out.println("아이폰 객체 생성 01");
	}
	/*
	public IPhone(Watch watch) {
		this.watch = watch;
		System.out.println("아이폰 객체 생성 02");
	}
	
	public IPhone(Watch watch, int num) {
		this.watch = watch;
		this.num = num;
		System.out.println("아이폰 객체 생성 03");
	}
	*/
//	init-method="initMethod"를 bean에 추가
	
	@Override
	public void powerOn() { // 아이폰은 워치에 대해 의존성을 갖는다.
		this.watch.powerOn();
		System.out.println("아이폰 전원 ON");
	}

	@Override
	public void powerOff() {
		this.watch.powerOff();
		System.out.println("아이폰 전원 OFF");
	}
	
	
	// getter,setter는 코드 하단에 기입하는것이 일반적
	public Watch getWatch() {
		return watch;
	}

	public void setWatch(Watch watch) {
		this.watch = watch;
	}
	
	
}

 


<AppleWatch.java>

package test;

public class AppleWatch implements Watch {
	
	public AppleWatch() {
		System.out.println("애플워치 생성자 호출");
	}
	
	@Override
	public void powerOn() {
		System.out.println("애플워치로 폰 전원 ON");
	}

	@Override
	public void powerOff() {
		System.out.println("애플워치로 폰 전원 OFF");
	}

}

 

 

 

2024.10.04