1cm

자바 프로그래밍_Day_103_Spring DI 본문

국비지원_Java/Java Programming_2

자바 프로그래밍_Day_103_Spring DI

dev_1cm 2022. 1. 27. 02:39
반응형

2022. 01. 12

 

 

클래스패스에서 가져오는 것을 선호한다.

 

name 대신에 index를 사용해서 구분도 가능하다.

 

 

스프링 3.0부터 지원되는 xml namespace c와 p를 추가시켜줬다. (xmlns:c, p)

 

<?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:c="http://www.springframework.org/schema/c"
   	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">

 

c:namespace 활용

ref가 없는 애들 : 리터럴 값을 넘겨줄 때 사용하게 됨

ref가 있는 애들 : 다른 bean을 참조하기 위해 씀

 

기존 namespace보다 간결하게 작성할 수 있다.

-> 생성자의 인자값을 bean태그의 속성값으로 선언하기 위해서 사용한다.

<bean id="owner" class="com.kh.di.owner.Owner" c:name="홍길동" c:age="20" c:pet-ref="cat"/>

 

아니면 몇 번째 인자번호인지 넣어서도 사용할 수 있다.

<bean id="owner" class="com.kh.di.owner.Owner" c:_0="홍길동" c:_1="20" c:_2-ref="cat"/>

 

 

생성자의 매개값이 하나일 경우 c_="매개값"으로도 표현이 가능하다. 

	 <!-- 
	 	Pet pet = new Cat("나비")
	 	
	 <bean id="cat" class="com.kh.di.pet.Cat">
	 	<constructor-arg name="name" value="나비"/>
	 </bean>
	  -->
	 <!-- 생성자의 매개값이 하나일 경우 아래와 같이 작성이 가능하다. -->
	 <bean id="cat" class="com.kh.di.pet.Cat" c:_="초롱이"/>

 

xmlns:p 적용 : c처럼 일반 리터럴일 경우 ref가 없는 것으로, 다른 bean을 참조할 경우 ref가 붙은 것으로 사용한다.

 

p는 setter로 주입한다.

<bean id="dog" class="com.kh.di.pet.Dog" p:name="인절미" />

 

 

보통 context파일을 연관된 애들끼리 나눠서 관리를 하기 때문에 실습에서도 그렇게 나눠주는 작업을 진행한다.

src > spring에 owner-context.xml > 

beans의 디폴트로 사용시 맨 위에 것 사용.

 

 

 

c, p도 같이 추가해줌

 

이렇게 생성된다.

 

 

그리고 root-context.xml에 있는 owner에 대한 bean을 옮겨줌

<?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:c="http://www.springframework.org/schema/c"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<!-- 
	기존 방식 : 
	Owner owner = new Owner("홍길동", 20, new Cat("나비"));

	 <bean id="owner" class="com.kh.di.owner.Owner">
	 	<constructor-arg name="name" value="홍길동" />
	 	<constructor-arg name="age" value="20" />
	 	<constructor-arg name="pet" ref="dog" />
	 </bean>
 	 	
	 <bean>
	 * name 대신에 index를 사용해서 구분할 수도 있다.
	 <constructor-arg index="0" value="홍길동" />
 	 <constructor-arg index="1" value="20" />
 	 <constructor-arg index="2" ref="dog" /> 
 	 </bean>

	 
	 <bean id="owner" class="com.kh.di.owner.Owner" c:_0="홍길동" c:_1="20" c:_2-ref="dog"/>
	 -->
	 
	 <bean id="mrhong" class="com.kh.di.owner.Owner" c:name="홍길동" c:age="20" c:pet-ref="cat"/>
	 <bean id="dongdong" class="com.kh.di.owner.Owner" c:name="동동이" c:age="30" c:pet-ref="dog"/>
	 
</beans>

 

 

 

그 다음 pet-context.xml 파일을 만들어준 뒤, beans, c, p를 추가해준다.

그리고 pet-context.xml파일에 root-context.xml에 있던 pet들에 대한 bean들을 다 옮겨줌

 

 

<?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:c="http://www.springframework.org/schema/c"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	
	 <!-- 
	 	Pet pet = new Cat("나비")
	 	
	 <bean id="cat" class="com.kh.di.pet.Cat">
	 	<constructor-arg name="name" value="나비"/>
	 </bean>
 
	 	Pet pet = new Dog();
	 	
	 	pet.setName("댕댕이");
	 	
	 <bean id="dog" class="com.kh.di.pet.Dog">
	 	<property name="name" value="댕댕이"/>
	 </bean>
	  -->
	  
	 <!-- 생성자의 매개값이 하나일 경우 아래와 같이 작성이 가능하다. -->
	 <bean id="cat" class="com.kh.di.pet.Cat" c:_="초롱이"/>
	 <bean id="dog" class="com.kh.di.pet.Dog" p:name="인절미" />
	 
</beans>

 

 

 

그리고 OwnerTest.java에서 보면 이미 root-context.xml을 포함하고 있으므로 root-context.xml에서 pet과 owner를 import시켜주는 작업을 진행

 

 

> root-context.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:c="http://www.springframework.org/schema/c"
   	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<!-- Root Context: defines shared resources visible to all other web components -->
	
	<!-- 다른 설정 파일을 가져오기 위해 사용되는 태그 -->
	<import resource="owner-context.xml" />
	<import resource="pet-context.xml" />
	
</beans>

 

 

테스트가 실행이 될 때, 설정파일을 만들어서 알아서 애플리케이션 컨텍스트를 만들어 줄 수 있게 해주는 dependency를 pom.xml에 추가시켜줌

 

추가 후 OwnerTest.java에 @ExtendWith(SpringExtension.class)를 붙여줬다.

 

 

context에게 설정 파일을 알려주기 위해 @ContextConfiguration 어노테이션을 추가해준다.

 

두 어노테이션을 붙여줬는데, mrhong이라는 bean을 getBean을 통해서 어떻게 가져올 것인가?

 

 

-> hong이라는 객체를 가져오려고 함

 

 

진짜 null인지 테스트 진행

 

 

@Autowired, @Qualifier("mrhong")을 추가해줬다.

-> 실제로 프로젝트나 애플리케이션에서는 실행할 때 필요한 빈들을 먼저 context가 만들 것이고, 주입받아서 쓰게 된다. (어노테이션 활용 @ExtendWith, @ContextConfiguration)

 

 

 

 

xml context에서 읽어갈 설정파일을 java-config로 만들기

-> 이 설정파일은 비즈니스 로직을 포함하거나 로직에 영향을 주지도 않음

-> 애플리케이션 컨텍스트가 읽어가서 빈을 만들 때 활용할 설정 파일이라고 보면 됨

 

클래스 생성

 

 

 

package com.kh.di.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.kh.di.owner.Owner;
import com.kh.di.pet.Cat;
import com.kh.di.pet.Dog;

// Configuration이 추가 되어야만 해당 자바 클래스가 애플리케이션 컨텍스트의 설정파일이라고 선언한다고 볼 수 있다.
@Configuration
public class RootConfig {
	
	@Bean
	// Bean을 넘겨주기 위한 메소드
	public Dog dog() {
		// 리턴하는 객체를 생성자를 통해서 Bean으로 등록하게 됨
		return new Dog("댕댕이");
	}
	
	@Bean("kitty")
	public Cat cat() {
		Cat cat = new Cat();
		
		cat.setName("kitty");
				
		return cat;
	}
	
	// Bean에 Id를 별도로 지정해주지 않으면 메소드명으로 Id를 지정한다. (owner)
	@Bean
	public Owner owner() {
		return new Owner("홍길동", 20, null);
	}
}

owner, cat, dog에 대한 Bean 들을 만들어 줬다.

 

이 Bean들을 어떻게 연결 시켜줄 것인가?

1. 메소드 직접 호출하는 방법

-> 메소드를 호출한다고 해도 이미 Bean으로 등록 되어 있기 때문에 application context에서 자동으로 등록된 Bean을 넣어준다.

 

	// Bean에 Id를 별도로 지정해주지 않으면 메소드명으로 Id를 지정한다. (owner)
	@Bean
	public Owner owner() {
		// dog() 메소드는 빈으로 등록되어 있기 때문에 호출 시마다 객체를 생성하는 것이 아닌
		// 애플리케이션 컨텍스트에서 등록된 Bean 객체를 리턴한다.
		return new Owner("홍길동", 20, dog());
	}

 

 

-> Test 진행

 

GenericXml보다 ApplicationContext가 더 상위에 있기 때문에 (다형성), ApplicationContext = GenericXmlApplication이 들어갈 수 있다.

 

	// 애플리케이션 컨텍스트를 통해 객체를 가져오기
	@Test
	public void contextTest() {
		// 스프링의 애플리케이션 컨텍스트를 활용하여 객체 간의 결합을 더욱 느슨하게 만들어준다.
		// new GenericXmlApplicationContext(클래스패스 상의 xml 파일의 위치 지정");
		ApplicationContext context = 
//			new GenericXmlApplicationContext("spring/root-context.xml");
//			new GenericXmlApplicationContext("classpath:spring/root-context.xml");
//			new GenericXmlApplicationContext("file:src/main/resources/spring/root-context.xml");
//			new GenericXmlApplicationContext("spring/owner-context.xml", "spring/pet-context.xml");
			// 설정 파일로 쓸 자바 파일을 명시해주면 된다.
			new AnnotationConfigApplicationContext(RootConfig.class);

설정파일로 쓸 자바파일을 명시만 해줘도 되는 이유?

 -> 같은 자바 파일이고, import가 되어있고, class에 Bean이 붙어있는 메소드를 가지고 Bean도 만들어주고 연결도 시켜줌

Application context의 설정을 바꾼 값으로 잘 출력이 되는 것을 확인

 

 

 

 

두 번째 방법

 

	@Bean("dongdong")
	public Owner owner2(@Autowired @Qualifier("kitty") Pet pet) {
		return new Owner("동동이", 30, pet);
	}

새로운 owner2를 만들어줬다.

 

그 다음 @ContextConfiguration(classes = {RootConfig.class})의 어노테이션을 만들어줬다.

 

 

그리고 context파일을 owner와 pet들로 나눴던 것 처럼 config파일도 Owner,Pet config파일을 만들어준 뒤, RootConfig에 있던 owner, pet에 대한 빈들을 각각 옮겨준다.

 

> OwnerConfig.java

package com.kh.di.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.kh.di.owner.Owner;
import com.kh.di.pet.Pet;

@Configuration
public class OwnerConfig {
	// Bean에 Id를 별도로 지정해주지 않으면 메소드명으로 Id를 지정한다. (owner)
	@Bean("mrhong")
	public Owner owner() {
		// dog() 메소드는 빈으로 등록되어 있기 때문에 호출 시마다 객체를 생성하는 것이 아닌
		// 애플리케이션 컨텍스트에서 등록된 Bean 객체를 리턴한다.
		return new Owner("홍길동", 25, dog());
	}
	
	@Bean("dongdong")
	// Autowired는 생략 가능 : 현재 파일은 설정파일인데, 매개값으로 받는 객체가 있으면 application context상에 Pet 타입의 Bean이 있는지 확인
	// -> 있으면 주입해준다.
	// 만약 Qualifier를 생략해주고 싶다면 @Primary를 달아준다.
	public Owner owner2(@Autowired @Qualifier("kitty") Pet pet) {
		return new Owner("동동이", 30, pet);
	}
}

-> dog()에서 에러 발생 -> OwnerConfig에 dog()라는 메소드가 없어서 발생하는 에러 -> dog라는 bean을 주입해줘야 함

	// Bean에 Id를 별도로 지정해주지 않으면 메소드명으로 Id를 지정한다. (owner)
	@Bean("mrhong")
	public Owner owner(@Autowired @Qualifier("dog") Pet pet) {
		// dog() 메소드는 빈으로 등록되어 있기 때문에 호출 시마다 객체를 생성하는 것이 아닌
		// 애플리케이션 컨텍스트에서 등록된 Bean 객체를 리턴한다.
		return new Owner("홍길동", 25, pet);
	}

위처럼 owner에 넣어준다.

만약 mrhong의 빈을 만들 때 애플리케이션 컨텍스트에 Pet타입의 pet이 없는 경우 일단 보류 -> 한바퀴 돌고 다시 보류된 부분을 확인해서 주입된다.

 

 

 

 

 > PetConfig.java

package com.kh.di.config;

import org.springframework.context.annotation.Bean;

import com.kh.di.pet.Cat;
import com.kh.di.pet.Dog;

@Configuration
public class PetConfig {
	@Bean
	// Bean을 넘겨주기 위한 메소드
	public Dog dog() {
		// 리턴하는 객체를 생성자를 통해서 Bean으로 등록하게 됨
		return new Dog("댕댕이");
	}
	
	@Bean("kitty")
	// <bean primary="true" />와 같다.
//	@Primary
	public Cat cat() {
		Cat cat = new Cat();
		
		cat.setName("kitty");
				
		return cat;
	}
}

 

 

- 테스트 실행시킬 때 에러 발생 -> bean을 찾을 수 없다고 나옴

-> xml로 진행 시

1. import

2. application context에 두 개의 config를 읽을수 있게 한다.

 > RootConfig 파일에 @Import를 추가시켜주는 방법

 

 > OwnerTest에 @Contextconfiguration에 추가 시켜주는 방법

 

 

웬만하면 첫 번째 방법을 쓰는 것을 권장

 

 

 

@어노테이션으로 Spring DI 활용

- 패키지 구조만 만들어 놓기

- 캐릭터 / 무기를 가질 수 있다

- 캐릭터 / 활을 쏠 수 있다.

 

character class 생성

 

package com.kh.di.character;

import com.kh.di.character.weapon.Weapon;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Character {
	private String name;
	
	private int level;
	
	// 인터페이스
	private Weapon weapon;
}

 

 

여러 가지의 무기들을 코드 수정없이 사용하기 위해 무기 인터페이스를 만들어줌

 

 

package com.kh.di.character.weapon;

public interface Weapon {
	// 무기마다 공격 방식이 다르기 때문에 어떻게 공격할 것인지에 대한 설정 - 추상 메소드
	public String attack();
}

 

칼에 대한 클래스 생성하면서 무기 인터페이스 참조할 수 있도록 추가시켜줌

 

 

package com.kh.di.character.weapon;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Sword implements Weapon {
	
	// 칼(무기)에대한 이름
	private String name;

	@Override
	public String attack() {

		return "검을 휘두른다.";
	}

}

 

 

그 다음 활(무기) class 만들어줌

package com.kh.di.weapon;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Bow implements Weapon {
	
	// 활에 대한 이름
	private String name;
	
	@Override
	public String attack() {

		return "활을 쏜다. 슉!";
	}
}

 

 

CharacterTest 만들어줬다.

 

 

package com.kh.di.character;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import com.kh.di.weapon.Sword;

class CharacterTest {

	@Test
	@Disabled
	public void test() {
	}
	
	@Test
	public void create() {
		// new Character(캐릭터 이름, 레벨, 무기("무기명"));
		Character character = new Character("알렉산더", 1, new Sword("의검"));
		
		assertThat(character).isNotNull();
		assertThat(character.getWeapon()).isNotNull();
	}

}

 

 

 

 

 

실습 전체 코드

 

 

 > OwnerTest.java

package com.kh.di.owner;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import com.kh.di.config.OwnerConfig;
import com.kh.di.config.PetConfig;
import com.kh.di.config.RootConfig;
import com.kh.di.pet.Cat;
import com.kh.di.pet.Dog;

// JUnit에서 스프링을 사용할 수 있도록 SpringExtension.class를 사용하여 기능을 확장한다.
// 해당 설정이 있어야 @ContextConfiguration()을 통해서 설정 파일을 고, 애플리케이션 컨텍스트를 생성할 수 있다.
@ExtendWith(SpringExtension.class)
//@ContextConfiguration(locations = {"classpath:spring/root-context.xml"})
@ContextConfiguration(classes = {RootConfig.class})
//@ContextConfiguration(classes = {
//				OwnerConfig.class,
//				PetConfig.class
//				})
class OwnerTest {
	
	// 애플리케이션 컨텍스트 상에서 클래스 타입과 일치하는 빈을 자동으로 주입시켜준다.
	// 이 때 동일한 클래스 타입에 빈이 여러 개 존재할 경우 @Qualifier("bean ID")를 명시적으로 넣어주어야 한다.
	// 직접적으로 @QUalifier를 주지 않고도 애플리케이션 컨텍스트 상에서 겹치는 타입의 빈이 여러 개 있을 때 primary="true"로 기본 빈을 지정할 수 있다.
	// -> owner-context.xml에서 확인 가능
	@Autowired
	@Qualifier("dongdong")
	// 가져오려는 객체 : 아무것도 안 넣어주면 null이 들어감 (JVM에서 기본적으로 넣어줌)
	private Owner owner;

	@Test
	@Disabled
	public void nothing() {
	}
	
	@Test
	public void create() {
		// 기존에 자바 애플리케이션에서는 다형성과 생성자 주입을 통해 객체간의 결합을 느슨하게 만들어 준다.
		Owner owner = new Owner("홍길동", 20, new Cat("나비"));
		
		assertThat(owner).isNotNull();
		assertThat(owner.getPet()).isNotNull();
	}
	
	// 애플리케이션 컨텍스트를 통해 객체를 가져오기
	@Test
	public void contextTest() {
		// 스프링의 애플리케이션 컨텍스트를 활용하여 객체 간의 결합을 더욱 느슨하게 만들어준다.
		// new GenericXmlApplicationContext(클래스패스 상의 xml 파일의 위치 지정");
		ApplicationContext context = 
//				new GenericXmlApplicationContext("spring/root-context.xml");
//				new GenericXmlApplicationContext("classpath:spring/root-context.xml");
//				new GenericXmlApplicationContext("file:src/main/resources/spring/root-context.xml");
//				new GenericXmlApplicationContext("spring/owner-context.xml", "spring/pet-context.xml");
				// 설정 파일로 쓸 자바 파일을 명시해주면 된다.
				new AnnotationConfigApplicationContext(RootConfig.class);
				
		
		// object로 가져온 후 형변환
//		Owner owner = (Owner) context.getBean("owner");
		// 두 번째 매개값에 bean을 가져올 때 변환해서 가져올 타입 명시
//		Owner owner = context.getBean("owner", Owner.class);
		Owner owner = context.getBean("dongdong", Owner.class);
		
		assertThat(owner).isNotNull();
		assertThat(owner.getPet()).isNotNull();
	}
	
	@Test
	public void autoWiredTest() {
		assertThat(owner).isNotNull();
		assertThat(owner.getPet()).isNotNull();
		assertThat(owner.getPet().bark()).isNotNull().isEqualTo("야옹~");
	}
	
}

 

 

 > owner-context.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:c="http://www.springframework.org/schema/c"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<!-- 
	기존 방식 : 
	Owner owner = new Owner("홍길동", 20, new Cat("나비"));

	 <bean id="owner" class="com.kh.di.owner.Owner">
	 	<constructor-arg name="name" value="홍길동" />
	 	<constructor-arg name="age" value="20" />
	 	<constructor-arg name="pet" ref="dog" />
	 </bean>
 	 	
	 <bean>
	 * name 대신에 index를 사용해서 구분할 수도 있다.
	 <constructor-arg index="0" value="홍길동" />
 	 <constructor-arg index="1" value="20" />
 	 <constructor-arg index="2" ref="dog" /> 
 	 </bean>

	 
	 <bean id="owner" class="com.kh.di.owner.Owner" c:_0="홍길동" c:_1="20" c:_2-ref="dog"/>
	 -->
	 
	 <!-- <bean id="mrhong" primary="true" class="com.kh.di.owner.Owner" c:name="홍길동" c:age="20" c:pet-ref="cat"/> -->
	 <bean id="mrhong" class="com.kh.di.owner.Owner" c:name="홍길동" c:age="20" c:pet-ref="cat"/>
	 <bean id="dongdong" class="com.kh.di.owner.Owner" c:name="동동이" c:age="30" c:pet-ref="dog"/>
	 
</beans>

 

 

 

 > pet-context.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:c="http://www.springframework.org/schema/c"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	
	 <!-- 
	 	Pet pet = new Cat("나비")
	 	
	 <bean id="cat" class="com.kh.di.pet.Cat">
	 	<constructor-arg name="name" value="나비"/>
	 </bean>
 
	 	Pet pet = new Dog();
	 	
	 	pet.setName("댕댕이");
	 	
	 <bean id="dog" class="com.kh.di.pet.Dog">
	 	<property name="name" value="댕댕이"/>
	 </bean>
	  -->
	  
	 <!-- 생성자의 매개값이 하나일 경우 아래와 같이 작성이 가능하다. -->
	 <bean id="cat" class="com.kh.di.pet.Cat" c:_="초롱이"/>
	 <bean id="dog" class="com.kh.di.pet.Dog" p:name="인절미" />
	 
</beans>

 

 

 

 

 > root-context.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:c="http://www.springframework.org/schema/c"
   	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<!-- Root Context: defines shared resources visible to all other web components -->
	
	<!-- 다른 설정 파일을 가져오기 위해 사용되는 태그 -->
	<import resource="owner-context.xml" />
	<import resource="pet-context.xml" />
	
</beans>

 

 

 

 

 > OwnerConfig.java

package com.kh.di.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.kh.di.owner.Owner;
import com.kh.di.pet.Pet;

@Configuration
public class OwnerConfig {
	// Bean에 Id를 별도로 지정해주지 않으면 메소드명으로 Id를 지정한다. (owner)
	@Bean("mrhong")
	public Owner owner(@Autowired @Qualifier("dog") Pet pet) {
		// dog() 메소드는 빈으로 등록되어 있기 때문에 호출 시마다 객체를 생성하는 것이 아닌
		// 애플리케이션 컨텍스트에서 등록된 Bean 객체를 리턴한다.
		return new Owner("홍길동", 25, pet);
	}
	
	@Bean("dongdong")
	// Autowired는 생략 가능 : 현재 파일은 설정파일인데, 매개값으로 받는 객체가 있으면 application context상에 Pet 타입의 Bean이 있는지 확인
	// -> 있으면 주입해준다.
	// 만약 Qualifier를 생략해주고 싶다면 @Primary를 달아준다.
	public Owner owner2(@Autowired @Qualifier("kitty") Pet pet) {
		return new Owner("동동이", 30, pet);
	}
}

 

 

 

 

 > PetConfig.java

package com.kh.di.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.kh.di.pet.Cat;
import com.kh.di.pet.Dog;

@Configuration
public class PetConfig {
	@Bean
	// Bean을 넘겨주기 위한 메소드
	public Dog dog() {
		// 리턴하는 객체를 생성자를 통해서 Bean으로 등록하게 됨
		return new Dog("댕댕이");
	}
	
	@Bean("kitty")
	// <bean primary="true" />와 같다.
//	@Primary
	public Cat cat() {
		Cat cat = new Cat();
		
		cat.setName("kitty");
				
		return cat;
	}
}

 

 

 

> RootConfig.java

package com.kh.di.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.annotation.Primary;

import com.kh.di.owner.Owner;
import com.kh.di.pet.Cat;
import com.kh.di.pet.Dog;
import com.kh.di.pet.Pet;

// Configuration이 추가 되어야만 해당 자바 클래스가 애플리케이션 컨텍스트의 설정파일이라고 선언한다고 볼 수 있다.
@Configuration
@Import(value = {
		OwnerConfig.class,
		PetConfig.class
		})
// 참고용 : 자바에서 다른 설정 파일을 가져오고 싶을 때(XML) 사용
//@ImportResource(location = {"classpath"})
public class RootConfig {
	/*
	@Bean
	// Bean을 넘겨주기 위한 메소드
	public Dog dog() {
		// 리턴하는 객체를 생성자를 통해서 Bean으로 등록하게 됨
		return new Dog("댕댕이");
	}
	
  	// Bean에 Id를 별도로 지정해주지 않으면 메소드명으로 Id를 지정한다. (owner)
  	@Bean("mrhong")
	public Owner owner() {
		// dog() 메소드는 빈으로 등록되어 있기 때문에 호출 시마다 객체를 생성하는 것이 아닌
		// 애플리케이션 컨텍스트에서 등록된 Bean 객체를 리턴한다.
		return new Owner("홍길동", 25, dog());
	}
	*/

}

 

 

 

 

 > Owner.java

package com.kh.di.owner;

import com.kh.di.pet.Cat;
import com.kh.di.pet.Dog;
import com.kh.di.pet.Pet;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Owner {
	private String name;
	
	private int age;
	
	private Pet pet;
	
	
}

 

 

 > Pet.java

package com.kh.di.pet;

public interface Pet {
	// 추상 메소드 생성 (Cat, Dog 공통적으로 들어가는 메소드를 추상화 해줌)
	public String bark();
}

 

 

 

 > Dog.java

package com.kh.di.pet;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dog implements Pet{
	private String name;
	
	@Override
	public String bark() {
		return "멍멍!";
	}
}

 

 

 

 > Cat.java

package com.kh.di.pet;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Cat implements Pet{
	private String name;
	
	@Override
	public String bark() {
		return "야옹~";
	}
}

 

 

캐릭터 + 무기에 대한 코드는 위에 작성한 것이 전부

반응형
Comments