의존성 주입
Spring Framework가 지원하는 핵심 기능으로 객체 사이의 의존 관계가 객체 자신이 아닌 외부(조립기)에 의해 설정된다. 외부 조립기는 xml 설정 파일을 기반으로 의존을 설정한다.
package member.dao; public interface Dao { // public abstract void insert(); void insert(); void select(); void delete(); void update(); }
package member.dao; public class MemberDao implements Dao { @Override public void insert() { System.out.println("회원 정보 데이터베이스 저장"); } @Override public void select() { System.out.println("회원 정보 검색"); } @Override public void delete() { System.out.println("회원 정보 삭제"); } @Override public void update() { System.out.println("회원 정보 수정"); } }
생성자 타입의 주입방식
package member.service; import member.dao.Dao; public class MemberRegService implements MemberService { // Dao dao = new MemberDao(); // 의존성이 높은 코드이므로 X /* 생성자 방식 */ private Dao dao; // 주입받아야하는 참조변수 // 생성자를 통해서 Dao타입의 인스턴스를 주입받는다. // Dao dao = new MemberDao(); -> 다형성. public MemberRegService(Dao dao) { this.dao = dao; } @Override public Object process() { System.out.println("MemberRegService 실행"); dao.insert(); return null; } }
<?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/schema/beans/spring-beans.xsd"> <!-- MemberDao를 Bean(인스턴스)으로 등록 --> <bean id="memberDao" class="member.dao.MemberDao" > </bean> <!-- MemberRegService bean으로등록 --> <bean id="memberRegService" class="member.service.MemberRegService"> <!-- <constructor-arg ref="memberDao"/> --> <constructor-arg> <ref bean="memberDao"/> </constructor-arg> </bean> </beans>
프로퍼티 타입의 주입방식
package member.service; import member.dao.Dao; public class MemberInfoService implements MemberService{ /* 프로퍼티 타입 */ Dao dao; // 프로퍼티 타입의 주입 방식 : setter 메소드 정의가 필요하다 public void setDao(Dao dao) { this.dao = dao; } @Override public Object process() { System.out.println("MeberInfoService 실행"); dao.select(); return null; } }
<!-- 멤버인포서비스 Bean등록 --> <bean id="memberInfoService" class="member.service.MemberInfoService"> <!-- <property name="dao" ref="memberDao"></property> --> <property name="dao"> <ref bean="memberDao"/> </property>
MemberMain 실행
package member.main; import org.springframework.context.support.GenericXmlApplicationContext; import member.service.MemberInfoService; import member.service.MemberRegService; public class MemberMain { public static void main(String[] args) { //1. Spring 컨테이너 생성 GenericXmlApplicationContext ctx = new GenericXmlApplicationContext("classpath:appCtx.xml"); //2. MemberRegService 객체가 필요 MemberRegService regService = ctx.getBean("memberRegService", MemberRegService.class); //3. MemberRegService 프로세스 메서드 실행 regService.process(); //4. MemberinfoService 객체가 필요 MemberInfoService infoService = ctx.getBean("memberInfoService", MemberInfoService.class); //5. MemberInfoService 프로세스 메서드 실행 infoService.process(); } }

xml 설정파일
1. XML 네임스페이스를 이용한 프로퍼티 설정


<!-- 멤버인포서비스 Bean등록 --> <bean id="memberInfoService" class="member.service.MemberInfoService"> <!-- <property name="dao" ref="memberDao"></property> --> <property name="dao"> <ref bean="memberDao"/> </property> ↓ 아래처럼 간결해짐 <!-- 프로퍼티 방식에서 p를 사용하면 속성을 사용하지 않고 한 줄 처리가 가능 --> <!-- 멤버인포서비스 Bean등록 --> <bean id="memberInfoService" class="member.service.MemberInfoService" p:dao-ref="memberDao"> </bean> </beans>
2. 의존관계 설정 : 임의 빈 객체 전달
<bean id="memberInfoService" class="member.service.MemberInfoService"> <!-- <property name="dao" ref="memberDao"></property> --> <property name="dao"> <bean class="member.dao.MemberDao"/> </property>
3. 여러개의 xml 사용 / 두 개 이상의 설정파일 사용하기 > import 이용
<?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/schema/beans/spring-beans.xsd"> <import resource="classpath:appCtx4_1.xml"/> <import resource="classpath:appCtx4_2.xml"/> </beans>
DI - 의존관계자동설정

빈 객체 범위
xml에서 scope 설정
<?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/schema/beans/spring-beans.xsd"> <!-- MemberDao를 Bean(인스턴스)으로 등록 --> <bean id="memberDao" class="member.dao.MemberDao" > </bean> <!-- MemberRegService bean으로등록 --> <bean id="memberRegService" class="member.service.MemberRegService" scope="prototype" > <constructor-arg> <ref bean="memberDao"/> </constructor-arg> </bean> <!-- 멤버인포서비스 Bean등록 --> <bean id="memberInfoService" class="member.service.MemberInfoService" scope="singleton"> <property name="dao"> <bean class="member.dao.MemberDao"/> </property> </bean> </beans>
package member.main; import org.springframework.context.support.GenericXmlApplicationContext; import member.dao.Dao; import member.service.MemberInfoService; import member.service.MemberRegService; public class MemberMain2 { public static void main(String[] args) { //1. Spring 컨테이너 생성 GenericXmlApplicationContext ctx = new GenericXmlApplicationContext("classpath:appCtx5.xml"); Dao dao1 = ctx.getBean("memberDao", Dao.class); Dao dao2 = ctx.getBean("memberDao", Dao.class); // 아무 처리도 하지않으면 기본적으로 싱글톤이다. System.out.println("dao1참조변수 == dao2참조변수 ? " +(dao1==dao2)); //2. MemberRegService 객체가 필요 MemberRegService regService1 = ctx.getBean("memberRegService", MemberRegService.class); MemberRegService regService2 = ctx.getBean("memberRegService", MemberRegService.class); // 프로포타입이므로 false System.out.println("regService1==regService2 ? " + (regService1==regService2)); //4. MemberinfoService 객체가 필요 MemberInfoService infoService1= ctx.getBean("memberInfoService", MemberInfoService.class); MemberInfoService infoService2= ctx.getBean("memberInfoService", MemberInfoService.class); // 싱글톤타입이므로 true > 둘의참조변수가같다 System.out.println("infoService1==infoService2 ? " + (infoService1==infoService2)); } }

애노테이션 기반 설정
JDK5 버전부터 추가된 것으로 메타데이터를 XML등의 문서에 설정하는 것이 아니라 소스 코드에 “@애노테이션”의 형태로 표현하며 클래스, 필드, 메소드의 선언부에 적용 할 수 있는 특정 기능이 부여된 표현법이다. 프레임워크들이 활성화 되고 애플리케이션 규모가 커질수록 XML 환경 설정은 복잡해지는데, 이러한 어려움을 개선시키기 위하여 자바 파일에 애노테이션을 적용해서 코드를 작성함으로써 개발자가 설정 파일에 작업하게 될 때 발생시키는 오류의 발생 빈도를 낮춰주기도 한다.
Java 에서 이미 정의되어 있는 애노테이션
@Override - 메소드가 오버라이드 됐는지 검증.
부모 클래스 또는 구현해야 할 인터페이스에서 해당 메소드를 찾을 수 없다면 컴파일 오류.
@Deprecated - 메소드를 사용하지 말도록 유도. 만약 사용한다면 컴파일 경고.
@SuppressWarnings - 컴파일 경고를 무시.
@SafeVarargs - 제너릭 같은 가변인자 매개변수를 사용할 때 경고를 무시.(자바7 이상)
@FunctionalInterface - 람다 함수등을 위한 인터페이스를 지정.
메소드가 없거나 두 개 이상 되면 컴파일 오류.(자바 8이상)


@Autowired 애노테이션을 이용한 의존 자동 주입


xml 파일에서 annotation-config.
이전 코드보다 훨신 간결하게 프로퍼티나 생성자 부분 없이 깔끔해졌다.


@Autowired 애노테이션으로 인해 코드가 더깔끔해짐 (위-애노테이션 / 아래-프로퍼티&생성자방식)
@Qualifier 애노테이션을 이용한 의존 객체 선택
package member.dao; public class GuestDao implements Dao { @Override public void insert() { System.out.println("게스트 회원 정보 데이터베이스 저장"); } @Override public void select() { System.out.println("게스트 회원 정보 검색"); } @Override public void delete() { System.out.println("게스트 회원 정보 삭제"); } @Override public void update() { System.out.println("게스트 회원 정보 수정"); } }

memberDao를 복사해서 GuestDao를 만들어준 뒤 실행하면 dao가 두개라서 에러가 난다.


Qualifier를 이용해서 value값을 설정해주고 클래스에서 Qulifier 어노테이션으로 지정해준 후 Main 실행

@Autowired 의 필수 여부 지정

주석처리 하니 Dao가 없어서 에러가난다 (당연..)

없더라도 인스턴스는 생성되도록 한다.
대부분은 꼭 있어야하는 Dao같은 상황에 사용하지만, 존재의 유무를 확인할 때 등등 정리해서 쓰면 좋다.
@Resource 애노테이션을 이용한 자동 의존 주입


id를 name으로 써서 구별한다.
그러나 타입으로 구별하는 @autowired를 더 자주사용한다.
타입을 맞추는 것이 더 정확하고 에러가 덜 나기 때문이래나 뭐래나.. 암튼 그렇다!
자동 주입과 명시적 의존 주입 설정이 함께 사용되는 경우 명시적인 의존 주입 설정이 우선한다

[Spring] 의존객체 자동 주입(Automatic Dependency Injection), @Autowired, @Resource, @Inject
| 의존객체 자동 주입(Automatic Dependency Injection) 의존 객체 자동 주입(Automatic Dependency Injection)은 스프링 설정파일에서 혹은 태그로 의존 객체 대상을 명시하지 않아도 스프링 컨테이너가 자..
xzio.tistory.com
'spring' 카테고리의 다른 글
[스프링] jdbc (0) | 2021.01.11 |
---|---|
[스프링] 파일업로드 (0) | 2021.01.08 |
[스프링] MVC - 컨트롤러 구현 (0) | 2021.01.08 |
[스프링] MVC : 패턴 (0) | 2021.01.08 |
[스프링] 자바 프로젝트를 메이븐 기반의 프로젝트로 변환하기 (0) | 2021.01.06 |
[스프링] 기본 설정 (0) | 2021.01.05 |
[스프링] 설치 (0) | 2021.01.05 |