DI (Dependency Injection) 이란?

 

bean객체를 생성할 때, bean객체가 관리할 값이나 객체를 주입하는 것을 의미한다.

만약 ,객체가 생성될 때 해당 객체가 관리할 변수의 값이 정해져 있으면 알아서 bean객체가 생성될 때 변수에 값이 들어간다.

 

 

 

 

+ 2021-12-10 추가

의존하는 객체를 직접 생성하는 것이 아니라, 외부에서 생성한 후 주입하는 것.

DI를 할 때 정적인 클래스 의존관계동적인 클래스 의존관계를 생각해보아야 한다.

 

- 정적인 클래스 의존관계 ? import코드만 보고 의존관계를 파악할 수 있는 것. 애플리케이션을 실행하지 않아도 의존관계가 파악이 가능하다.

ex) public Car car = new porsche(); 

Car가 인터페이스이고 porsche가 구현 클래스라면 이 코드만 보고도 런타임 이전에 의존관계를 파악할 수 있다. 그리고 외부에서 의존관계를 주입하는 것이 아닌 직접 생성을 하고 있다.

 

 

- 동적인 클래스 의존관계 ? 런타임(실행)시점에서 의존관계를 파악할 수 있는 것.

ex) public final Car car;

Car가 인터페이스 이면 이 코드만 보고는 Car의 구현객체를 알 수 없으며 런타임 이전에 의존관계를 파악할 수가 없다. (car변수에는 생성자주입과 같은 방식으로 외부에서 주입을 받는다.)

 

 

DI를 할 때에는 코드에서는 런타임(실행)시점의 의존관계가 드러나지 않아야 한다. 즉, 동적인 클래스 의존관계여야 하며 이는 인터페이스에만 의존하고 있어야 한다는 의미와 같다. (객체지향적 설계를 위해 OCP, DIP원칙을 지키는 것과도 상통하다.)

런타임(실행)시점에서 실제 구현 객체를 생성하고 클라이언트에 주입(전달)함으로써 외부에서 의존관계를 결정해야 한다. 이와 같은 조건이 맞을 때 DI가 되었다고 한다.

 

 

 

 

 

 

 

 

 

 

 

TestBean클래스에 다음과 같이 생성자가 정의되어있다. 

기본생성자, 정수형 변수를 받는 생성자, 실수형 변수를 받는 생성자 이렇게 3개이다.

 

 

 

 

 

(printData메소드는 필드의 값을 프린트해주는 함수)

 

자바에서는 이렇게 new를 이용하여 새로운 객체를 만들어가면서 그 객체의 생성자의 매개변수에 정수형 변수, 실수형 변수를 넣으면 해당 변수의 타입에 알맞는 생성자를 찾아서 인스턴스 변수가 생성되게 된다.

 

이 작업을 spring xml에서 하려고 하면 어떻게 해야할까??

 

 

 

 

bean객체를 정의하는 bean태그안의 속성에 constructor-arg라는 태그를 추가한다.

constructor-arg태그의 속성중 value에는 생성자의 매개변수에 들어갈 변수의 value값이 들어가고 type은 매개변수의 타입이다.

 

spring에서는 String > double > int 순서로 우선순위를 가진다. 그러므로 만약 type속성을 아무것도 지정해주지 않았는데, TestBean 클래스에 String형을 매개변수로 받는 생성자가 정의되어 있다면 value값은 자동으로 String으로 인식된다.

 

최우선순위가 String이므로 만약 type이 String이면 굳이 써주지 않아도 되지만..

쓰고 싶다면, java는 String이 클래스이기 때문에 그냥 type="string" 이 아닌, type="java.lang.String" 과 같이 써주어야 하겠다.

 

 

 

 

또한 , 위와 같이 xml에 bean을 정의하는데 생성자를 통해 주입할때 생성자 매개변수의 순서는 크게 상관이 없다.

먼소리냐고?

 

 

 

 

 

 

생성자중에 다음과 같이 int, double, String 순서로 매개변수를 받는 생성자가 존재한다고 치자.

 

만약 자바에서,

 

 

이런식으로 객체를 생성했다면? 당연히 오류가 난다. 저런 매개변수를 갖는 생성자를 찾을 수 없기 때문이다.

 

그런데.. spring bean을 정의하는 xml에서는

 

 

 

이런식으로 정의한후

 

ClassPathXmlApplicationContext ctx = new CalssPathXmlApplicationContext("com/study/spring/config/bean.xml");
TestBean2 test2 = ctx.getBean("obj6", TestBean2.calss);
test2.printData();

 

이와 같이 하여도 오류가 나지 않는다는 것이다.

 

 

spring에서는 먼저, 정의된 생성자의 순서대로 값을 주입할 수 있는 생성자를 찾는다
근데 없다? 그러면 이 값을 모두 주입할 수있는 생성자를 찾는다! 

위의 예가 순서대로 값을 주입할 수 있는 생성자가 없어서 이 값을 모두 주입할 수 있는 생성자를 찾은 예가 되겠다.

 

 

 

 

 

 

 

 

객체주입

 

말로만 '객체주입' 이렇게 써놓으면 먼소린가 싶다 나도..

코드로 보자.

 

 

 

DataBean이라는 이름의 POJO class가 있다고 가정하고,

beans_data라는 이름의 bean을 정의한다. 이 bean은 prototype이니까 불러올 때마다 객체를 새로 생성한다.

 

obj7이라는 bean을 정의할때 생성자의 매개변수로서 beans_data를 2개 집어 넣는다.

대충 TestBean2가 어떻게 생겨먹었는지 유추할수 있다.

 

 

 

 

DataBean type의 매개변수 2개를 생성자에서 받는 형태는 xml에서 저렇게 정의한다.

data1과 data2는 서로 다른 변수여야 하기때문에 beans_data라는 prototype의 bean을 따로 정의해서 그 bean을 ref속성을 이용하여 집어 넣는 방법이다.

 

 

 

 

 

 

 

 

 

 

setter를 이용한 주입

 

위에 예제에서 사용된 DataBean이라는 POJO 클래스가 getter, setter가 정의되어 있다고 가정해보자.

 

 

 

 

다음과 같이 property태그를 이용하여 setter주입을 할 수 있다.

 

name이 data1이니까 setData1을 자동으로 찾아가고, value의 값을 매개변수로 자동으로 넣어준다.

property의 name 맨 앞글자를 대문자로(D) 바꾸고 앞에 set을 붙여 setData1이라는 함수를 찾는 방식으로 setter를 찾는다고 한다... (정확하진 않으나.. 강의에서 그랬음...)

 


만약 setData1이름의 메소드가 매개변수만 다르게 여러개있으면 value는 String > double > int 우선순위 순서대로 들어감

'JAVA > Spring' 카테고리의 다른 글

자동 주입  (0) 2020.04.10
컬렉션 주입  (0) 2020.04.09
Bean 객체의 생성시점과 생명주기  (0) 2020.04.08
IoC 컨테이너  (0) 2020.04.07
Maven 설정  (0) 2020.04.07

+ Recent posts