스프링 DI 지시서 작성하기(Spring bean Configuration)

2022. 5. 17. 20:16spring

public interface Exam {
	int total();
	float avg();
}

_________________________________________________________________________


구현을 명령받은 클래스 NewExam
public class NewExam implements Exam {

	private int kor;
	private int eng;
	private int math;
	private int com;
	
	@Override
	public int total() {
		
		return kor + eng + math + com;
	}

	@Override
	public float avg() {

		return total() / 4.0f;
	}

}

_________________________________________________________________________


import spring.di.entity.Exam;

public interface ExamConsole {
	void print();

	void setExam(Exam exam);
}

_________________________________________________________________________


구현을 명령받은 클래스 
import spring.di.entity.Exam;

public class GridExamConsole implements ExamConsole {

private Exam exam;
	
	
	public GridExamConsole(Exam exam) {
		this.exam = exam;
	}
	public GridExamConsole() {
		// TODO Auto-generated constructor stub
	}
	@Override
	public void print() {
		System.out.println("total:"+ exam.total() + "avg:" + exam.avg());
	}
	@Override
	public void setExam(Exam exam) {
		this.exam = exam;
	}

}

_________________________________________________________________________


구현을 명령받은 클래스 
import spring.di.entity.Exam;

public class InlineExamConsole implements ExamConsole {

	private Exam exam;
	
	
	public InlineExamConsole(Exam exam) {
		this.exam = exam;
	}


	@Override
	public void print() {
		System.out.printf("total is %d, avg is %f\n", exam.total(), exam.avg());
	}


	@Override
	public void setExam(Exam exam) {
		this.exam = exam;
	}

}

_________________________________________________________________________

public class Program {

	public static void main(String[] args) {
		
		/* 스프링에게 지시하는 방법으로 코드를 변경
		Exam exam = new NewExam();
		ExamConsole console = new GridExamConsole();
		
		console.setExam(exam);
		*/
		
		ExamConsole console = ?;
		console.print();
	}
}

 

지시서 작성!

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/shema/beans/spring-beans-3.0.xsd">
	<!-- Exam exam = new NewExam -->
	<bean id="exam"    class="spring.di.entity.NewExam"/>
	<!-- ExamConsole console = new GridExamConsole() -->
	<bean id="console" class="spring.di.ui.GridExamConsole()">
		<!-- console.setExam(exam) -->
		<property name="exam" ref="exam"/> <!-- setExam을 호출한 것임 -->
	</bean>
</beans>

하지만 이 지시서를 전달해줄 객체가 하나 필요함

 

*)console 객체필드에 exam을 세팅할 때 ref를 쓴 이유는 exam이 원시형 변수가 아니고 참조형 변수기 때문

 

ApplicateionContext context = new

ClassPathXmlApplicationContext("config.xml");

 

 

ApplicationContext 생성하기

public class Program {

	public static void main(String[] args) {
		
		/* 스프링에게 지시하는 방법으로 코드를 변경
		Exam exam = new NewlecExam();
		ExamConsole console = new GridExamConsole();
		
		console.setExam(exam);
		*/
		
		/*
		 * 지시서에 따라 객체 2개를 만들고 인젝션까지 해서 보따리에 잘 담아놨다. 이 보따리가 ioC 컨테이너!
		 * */
		ApplicationContext context =
				new ClassPathXmlApplicationContext("spring/di/setting.xml"); //지시서 위치
		
		//ExamConsole console = (ExamConsole) context.getBean("console");
		ExamConsole console = context.getBean(ExamConsole.class); //인터페이스에 참조될 수 있는 객체 꺼내줌
		console.print();
	}
}

 

객체 생성할 때 필드에 값 넣기

<?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:util="http://www.springframework.org/schema/util"
	xmlns:p="http://www.springframework.org/schema/p"
	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.xsd">
	
	<context:annotation-config/>
	<!-- Exam exam = new NewlecExam -->
	<bean id="exam"  class="spring.di.entity.NewlecExam">
	
		<constructor-arg index="0" value="10"/>
		<constructor-arg index="1" value="20"/>
		<constructor-arg index="2" value="30"/>
		<constructor-arg index="3" value="40"/>
	
	</bean>  //객체를 생성해서 빈에 등록 할 때 Exam으로 구현을 명령받은 인터페이스의 필드에 값을 넣는다.
    
    <bean id="console" class="spring.di.ui.InlineExamConsole">
       	<property name="exam" ref="exam"/>
    </bean>
    
    ___________________________________________________________________________________
    
    
    <!--2번째 방안, 네임스페이스 사용하기(위에 빈 속성에 xmlns:p="http://www.springframework.org/schema/p"넣어야 가능)  -->
    <bean id="exam"  class="spring.di.entity.NewlecExam" p:kor="10" p:eng="10" p:math="10" p:com="10">
    </bean>
    
    <bean id="console" class="spring.di.ui.InlineExamConsole">
       	<property name="exam" ref="exam"/>
    </bean>
    
    
</beans>

 

 

@Autowired를 사용해 바인딩

 

    <?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:util="http://www.springframework.org/schema/util"
	xmlns:p="http://www.springframework.org/schema/p"
	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.xsd">
	
	<context:annotation-config/>
    
    <bean id="exam"  class="spring.di.entity.NewlecExam" p:kor="10" p:eng="10" p:math="10" p:com="10">
    </bean>
    
    <bean id="console" class="spring.di.ui.InlineExamConsole">
       	<!-- <property name="exam" ref="exam"/> -->				//Autowired를 사용해서 ExamConsole 클래스를 읽을때
    </bean>														//setter 메서드를 바인딩해 자동으로 설정




____________________________________________________________________________________________________________


구현을 명령받은 클래스 
import spring.di.entity.Exam;

public class InlineExamConsole implements ExamConsole {

	private Exam exam;
	
	
	public InlineExamConsole(Exam exam) {
		this.exam = exam;
	}


	@Override
	public void print() {
		System.out.printf("total is %d, avg is %f\n", exam.total(), exam.avg());
	}


	@Override
    @Autowired						
	public void setExam(Exam exam) {
		this.exam = exam;
	}

}

 

주의! xml에서 클래스를 읽어들일 때 <context:annotation-config/>를 사용해야 스프링이 어노테이션을 활성화 하고 해석 할 수 있다.

 

@Qualifier

bean에 id를 썼다만, 그 id가 가리키는 것이 매겨변수의 이름은 아니다. 그것은 빈에 등록되는 객체가 여러개일 때, 혹은 객체를 생성할 때 매개변수가 여러개가 들어간다면  @Qualifier("exam1"), @Qualifier("exam2") 이렇게 구분할 때 쓰인다.

 

@Qualifier는 세터,필드,생성자 위에서 바인딩 할 수 있다.

 

<bean id="exam1"    class="spring.di.entity.NewlecExam" p:kor="10" p:eng="10" p:math="10" p:com="10"></bean>
<bean id="exam2"    class="spring.di.entity.NewlecExam" p:kor="10" p:eng="10" p:math="10" p:com="50"></bean>



__________________________________________________________________________


package spring.di.ui;

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

import spring.di.entity.Exam;

public class InlineExamConsole implements ExamConsole {


	private Exam exam;
	
	public InlineExamConsole() {
		System.out.println("constructor");
	}
	public InlineExamConsole(Exam exam) {
		System.out.println("overroad constructor");
		this.exam = exam;
	}


	@Override
	public void print() {
		System.out.printf("total is %d, avg is %f\n", exam.total(), exam.avg());
	}

	@Autowired
	@Qualifier("exam2")
	@Override
	public void setExam(Exam exam) {
		System.out.println("setter");
		this.exam = exam;
	}
}

________________________________________________________________________________



package spring.di.ui;

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

import spring.di.entity.Exam;

public class InlineExamConsole implements ExamConsole {

	@Autowired
	@Qualifier("exam2")
	private Exam exam;
	
	public InlineExamConsole() {
		System.out.println("constructor");
	}
	public InlineExamConsole(Exam exam) {
		System.out.println("overroad constructor");
		this.exam = exam;
	}


	@Override
	public void print() {
		System.out.printf("total is %d, avg is %f\n", exam.total(), exam.avg());
	}


	@Override
	public void setExam(Exam exam) {
		System.out.println("setter");
		this.exam = exam;
	}
}



__________________________________________________________________________________

package spring.di.ui;

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

import spring.di.entity.Exam;

public class InlineExamConsole implements ExamConsole {


	private Exam exam;
	
	public InlineExamConsole() {
		System.out.println("constructor");
	}
    
    @Autowired
	public InlineExamConsole(@Qualifier("exam1")Exam exam1,
                             @Qualifier("exam2")Exam exam2) {
		System.out.println("overroad constructor");
		this.exam = exam;
	}


	@Override
	public void print() {
		System.out.printf("total is %d, avg is %f\n", exam.total(), exam.avg());
	}


	@Override
	public void setExam(Exam exam) {
		System.out.println("setter");
		this.exam = exam;
	}
}

 

@Component

 - 객체를 생성해서 빈에 등록해준다

 

package spring.di.ui;

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

import spring.di.entity.Exam;

@Component //위치!!!!!!!!!!!!
public class InlineExamConsole implements ExamConsole {

	@Autowired
	@Qualifier("exam2")
	private Exam exam;
	
	public InlineExamConsole() {
		System.out.println("constructor");
	}
	public InlineExamConsole(Exam exam) {
		System.out.println("overroad constructor");
		this.exam = exam;
	}


	@Override
	public void print() {
		System.out.printf("total is %d, avg is %f\n", exam.total(), exam.avg());
	}

	@Override
	public void setExam(Exam exam) {
		System.out.println("setter");
		this.exam = exam;
	}

}

______________________________________________________________________________

<?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:util="http://www.springframework.org/schema/util"
	xmlns:p="http://www.springframework.org/schema/p"
	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.xsd">
	
    <context:component-scan base-package="spring.di.ui"/>
	//<context:annotation-config/>
	<bean id="exam1"    class="spring.di.entity.NewlecExam" p:kor="10" p:eng="10" p:math="10" p:com="10"></bean>
	<bean id="exam2"    class="spring.di.entity.NewlecExam" p:kor="10" p:eng="10" p:math="10" p:com="50"></bean>
	<!-- 없애 버리기
	<bean id="console" class="spring.di.ui.InlineExamConsole">
		 console.setExam(exam) 
		 <property name="exam" ref="exam"/> setExam을 호출한 것임 
	</bean>
	 -->

 

주의!!!!! <context:annotation-config/>는 빈을 등록한 객체의 어노테이션만 스캔할 수 있다.

             <context:component-scan base-package="spring.di.ui"/>는 지정해둔 범위를 스캔하고 빈 등록과 관계없이 어노테이션을 가져다 쓸수 있다. 따라서 스캔을 하면 위에 것을 사용할 필요는 없음