- IoC/DI -객체지향 언어에서 Object 간의 연결 관계를 런타임에 결정 -객체 간의 관계가 느슨하게 연결됨 (결합도가 낮아짐, loose coupling) -IoC의 구현 방법 중 하나가 DI (Dependency Injection)
IoC 유형
Dependency Lookup
- JNDI (Java Name Directory Interface) - 컨테이너가 lookup context를 통해서 필요한 Resource나 Object를 얻는 방식 - JNDI 이외의 방법을 사용한다면 JNDI관련 코드를 오브젝트 내에서 일일이 변경해 주어야 함. - Lookup 한 Object를 필요한 타입으로 Casting 해 주어야 함. - Naming Exception을 처리하기 위한 로직이 필요.
Dependency Injection
- Object에 lookup 코드를 사용하지 않고 컨테이너가 직접 의존 구조를 Object에 설정할 수 있도록 지정해주는 방식 - Object가 컨테이너의 존재 여부를 알 필요가 없음 - Lookup 관련된 코드들이 Object 내에서 사라짐 - Setter Injection과 Constructor Inject
IoC 개념
● 객체 제어 방식 - 기존 : 필요한 위치에서 개발자가 필요한 객체 생성 로직 구현 - IoC : 객체 생성을 Container에게 위임하여 처리
● IoC 사용에 따른 장점 - 객체 간의 결합도를 떨어뜨릴 수 있음 (loose coupling)
● 객체 간 결합도가 높으면? - 해당 클래스가 유지보수될 때 그 클래스와 결합된 다른 클래스도 같이 유지보수되어야 할 가능성이 높다.
● 객체간 강한 결합 - 클래스 호출 방식 - 클래스 내에 선언과 구현이 모두 되어있기 때문에 다양한 형태로 변화가 불가능
- sample1 * HelloSpring 구현체를 MessageBean에서 직접 생성하여 사용한다. * HelloSpring이 교체되거나 내부 코드가 변경되면 MessageBean까지 수정해야 할 가능성이 있다.
▶ MessageBean.java
package sample1;
public class MessageBean {
public void sayHello(String name) {
//System.out.println("헬로우" + name);
System.out.println("Hello" + name);
}
}
▶ HelloSpring.java
package sample1;
//결합도가 높은 프로그램
public class HelloSpring {
public static void main(String[] args) {
MessageBean bean=new MessageBean();
//bean.sayHello(" 스프링!!");
bean.sayHello(" Spring!!");
}
}
▶ 결과
● 객체 간의 강한 결합을 다형성을 통해 결합도를 낮춘다.
- 인터페이스 호출 방식 - 구현 클래스 교체가 용이하여 다양한 형태로 변화 가능하다. - 하지만 인터페이스 교체 시 호출 클래스도 수정해야 한다. - sample2 * MessageBeanEn와 MessageBeanKr는 MessageBean를 상속 * HelloSpring에서 각 서비스를 이용 시 MessageBeanEn와 MessageBeanKr는 MessageBean 타입으로 사용 가능
▶ MessageBean.java
package sample2;
public interface MessageBean {
public void sayHello(String name);
}
▶ MessageBeanKr.java
package sample2;
public class MessageBeanKr implements MessageBean{
@Override
public void sayHello(String name) {
System.out.println("헬로우," + name);
}
}
▶ MessageBeanEn.java
package sample2;
public class MessageBeanEn implements MessageBean{
@Override
public void sayHello(String name) {
System.out.println("Hello," + name);
}
}
▶HelloSpring.java
package sample2;
//의존 관계를 약하게 설정하는 프로그램(결합도를 낮춤)
public class HelloSpring {
public static void main(String[] args) {
MessageBean bean=new MessageBeanEn();
//bean.sayHello(" 스프링!!");
bean.sayHello(" Spring!!");
}
}
▶ 결과
● 객체 간의 강한 결합을 Factory를 통해 결합도를 낮춘다.
- 팩토리 호출 방식 - 팩토리 방식은 팩토리가 구현 클래스를 생성하므로 클래스는 팩토리를 호출한다. - 인터페이스 변경 시 팩토리만 수정하면 된다. 호출 클래스에는 영향을 미치지 않는다. - 하지만 클래스에 팩토리를 호출하는 소스가 들어가야 한다. 그것 자체가 팩토리에 의존함을 의미한다.
- sample2.factory * 각 Bean을 생성하여 반환하는 Factory 사용 * Bean을 이용하는 쪽에서는 Interface만 알고 있으면 어떤 구현체가 어떻게 생성되는지에 대해서는 알 필요가 없다. *이 Factory 패턴이 적용된 것이 Container의 기능이며 이 Container의 기능을 제공해 주고자 하는 것이 IoC모듈
▶ MessageBean.java
package sample2.factory;
public interface MessageBean {
String sayHello(String name);
}
▶ MessageBeanKr.java
package sample2.factory;
public class MessageBeanKr implements MessageBean{
@Override
public String sayHello(String name) {
return "헬로우," + name;
}
}
▶ MessageBeanEn.java
package sample2.factory;
public class MessageBeanEn implements MessageBean{
@Override
public String sayHello(String name) {
return "Hello," + name;
}
}
▶ MessageBeanFactory.java
package sample2.factory;
public class MessageBeanFactory {
public static MessageBean getMessageBean(String lang) {
if("kor".equals(lang)) {
return new MessageBeanKr();
} else if("eng".equals(lang)) {
return new MessageBeanEn();
} else {
return null;
}
}
}
▶HelloSpring.java
package sample2.factory;
// 객체 간의 강한 결합을 Factory를 통해 결합도를 낮춘다.
public class HelloSpring {
public static void main(String[] args) {
//MessageBean bean= MessageBeanFactory.getMessageBean("kor");
MessageBean bean= MessageBeanFactory.getMessageBean("eng");
//System.out.println(bean.sayHello(" 스프링!!"));
System.out.println(bean.sayHello(" Spring!!"));
}
}
▶ 결과
● 객체 간의 강한 결합을 Assembler를 통해 결합도를 낮춘다.
- IoC 호출 방식 - 팩토리 패턴의 장점을 더하여 어떠한 것에도 의존하지 않는 형태가 됨. - 실행 시점(Runtime)에 클래스 간의 관계가 형성이 됨.
- sample3 * 각 Bean의 LifeCycle을 관리하는 Assembler를 사용한다. * Spring Container가 외부 조립기(Assembler) 역할을 한다.
▶ MessageBean.java
package sample3;
public interface MessageBean {
public void sayHello(String name);
}
▶ MessageBeanKr.java
package sample3;
public class MessageBeanKr implements MessageBean{
@Override
public void sayHello(String name) {
System.out.println("헬로우," + name);
}
}
▶ MessageBeanEn.java
package sample3;
public class MessageBeanEn implements MessageBean{
@Override
public void sayHello(String name) {
System.out.println("Hello," + name);
}
}
댓글