[Spring] 생성자를 통한 의존성 주입 (Dependency Injection)
의존성 주입(Dependency Injection)이란 xml이나 자바 파일에서 생성한 Bean객체가 관리하는 값이나 객체에 값을 주입해주는 것이다.
즉, Bean클래스가 가지고 있는 멤버 변수나 매개변수에 값을 세팅해주는 것을 의미한다.
의존성 주입은 생성자를 통한 방법, setter 메서드를 통한 방법, 자동 주입방법 등 여러 가지 방법이 있다.
생성자를 통한 방법은 생성자에 매개변수에 값을 Bean 설정 파일에서 값을 설정해주는 방법이다.
원래의 자바 문법에서 클래스의 생성자를 정의하고 생성자에 값을 넣는 코드는 아래와 같다.
//Bean 클래스
public class TestBean {
private int data1;
private double data2;
private String data3;
public TestBean(int data1, double data2, String data3) {
System.out.println("TestBean의 생성자");
this.data1 = data1;
this.data2 = data2;
this.data3 = data3;
}
public void printData() {
System.out.println("data1 : " + data1);
System.out.println("data2 : " + data2);
System.out.println("data3 : " + data3);
}
}
//메인 클래스
public class MainClass {
public static void main(String[] args) {
TestBean t1 = new TestBean(data1의 값, data2의 값, data3의 값)
t1.printData();
}
}
Bean 클래스에서 멤버변수를 정의하고 생성자의 매개변수에 값을 멤버 변수에 대입하고 이를 출력하는 예제이다.
원래 자바 문법에서는 위와 같은 코드를 이용하여 값을 주입하였다면 Bean 설정 파일에서 생성자를 통한 주입의 은 아래 코드와 같다.
먼저 해당 Bean클래스를 Bean 설정 파일에 등록한다. 그리고 <constructor-arg> 태그로 생성자에 매개변수에 값을 주입한다.
<!-- Bean 등록 후 <constructor-arg> 태그로 생성자에 매개변수에 값 주입 -->
<bean id="Bena의 id값" class="패키지 포함 클래스 명 " lazy-init="true">
<constructor-arg value="값1" />
<constructor-arg value="값2" />
<constructor-arg value="값3" />
</bean>
<!-- Bean 설정 파일에서 객체를 주입해주면 new 연산자로 객체를 생성하고 값을 주입할 필요가 없다. -->
//메인 클래스
public class MainClass {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("Bean 설정 파일의 패키지포함 이름");
TestBean t1 = ctx.getBean("Bean의 id", TestBean.class);
t1.printData();
ctx.close();
}
}
Bean 클래스의 매개변수의 수와 <constructor-arg>수를 비교하여 <constructor-arg>의 값을 차례대로 생성자에 매개변수에 주입한다.
즉, <constructor-arg>의 값 1은 TestBean 클래스 생성자에 매개변수 data1에 값 2는 data2에 주입되는 것이다.
위와 같이 세팅해준다면 위의 자바코드로 생성한 객체처럼 new연산자를 사용할 필요가 없어진다.
이때 주의해야 할 점은 Bean클래스에 생성자가 오버 로딩으로 같은 수의 매개변수를 가진 생성자가 여럿 있다면
스프링 프레임워크에 데이터타입 우선순위에 따라 원하는 생성자가 아닌 같은 매개변수의 개수를 가진 다른 생성자에 주입될 수 있다.
※ 스프링 프레임워크 데이터 타입 우선 순위 : 문자열 -> 실수 -> 정수
이를 방지하기 위하여 <constructor-arg>의 데이터 타입을 정해줄 수 있다.
<!-- Bean 등록 후 <constructor-arg> 태그로 생성자에 매개변수에 값 주입 -->
<bean id="Bena의 id값" class="패키지 포함 클래스 명 " lazy-init="true">
<constructor-arg value="값1" type="int" />
<constructor-arg value="값2" type="double" />
<constructor-arg value="값3" type="String" />
</bean>
위와 같이 세팅해준다면 값1은 int타입 매개변수에, 값 2는 double타입 매개변수를 찾아가서 주입된다.
또 한 <constructor-arg>의 index속성을 이용하여 순서를 정해줄 수도 있다.
<!-- Bean 등록 후 <constructor-arg> 태그로 생성자에 매개변수에 값 주입 -->
<bean id="Bena의 id값" class="패키지 포함 클래스 명 " lazy-init="true">
<constructor-arg value="값1" type="int" index="0" />
<constructor-arg value="값2" type="double" index="1" />
<constructor-arg value="값3" type="String" index="2" />
</bean>
index는 0부터 시작한다.
만약 주입할 값이 객체인 경우에는 해당 객체의 대한 Bean을 먼저 생성한 후 ref속성을 이용하여 주입한다.
<!-- ref 속성에는 주입할 객체의 Bean id값을 넣는다. -->
<bean id="Bena의 id값" class="패키지 포함 클래스 명 " lazy-init="true">
<constructor-arg ref="bean1" index="0" />
</bean>
<bean id="bean1" class="~~~~~~~" />
만약 아래와 같은 Bean 클래스가 있을 경우 이를 생성자를 통한 주입으로 값을 주입하게 된다면 아래와 같다.
(1) Bean 클래스 작성
// Bean 클래스
public class TestBean2 {
private int data1;
private double data2;
private String data3;
private DataBean data4;
public TestBean2(int data1, double data2, String data3, DataBean data4) {
this.data1 = data1;
this.data2 = data2;
this.data3 = data3;
this.data4 = data4;
}
public void printData() {
System.out.println("data1 : " + data1);
System.out.println("data2 : " + data2);
System.out.println("data3 : " + data3);
System.out.println("data4 : " + data4);
}
}
(2) xml파일에서 Bean 생성과 <constructor-arg> 속성에 값을 주입
<!-- Bean 설정 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"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="bean1" class="패키지 포함 클래스 이름" lazy-init="true">
<constructor-arg value="10" type="int" index="0" />
<constructor-arg value="11.11" type="double" index="1" />
<constructor-arg value="문자열" type="String" index="2" />
<constructor-arg ref="bean2"/>
</bean>
<bean id="bean2" class="패키지 포함 클래스 이름" />
</beans>
(3) 메인 클래스에서 xml파일을 로딩하고 getBean으로 객체를 생성
public class MainClass {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("xml파일의 패키지 포함 이름");
TestBean2 bean = ctx.getBean("bean1", TestBean2.class);
bean.printData();
ctx.close();
}
}
위 코드를 실행했을 때의 결과는 아래와 같다.
로그를 보면 Bean 설정 xml파일에서 설정한 값들이 생성자의 매개변수에 주입되어서 printData( ) 메서드에 의해 출력되는 것을 확인할 수 있다.
본 포스팅은 필자가 공부한 내용을 정리한 것으로 오류가 존재할 수 있습니다.
참고: 인프런 - 스프링 프레임워크 개발자 양성을 위한 실습을 통한 입문 과정