본문 바로가기
Java Web Programming/6. Spring | MyBatis

[Spring] 스프링 IOC/DI Annotation 어노테이션

by 파프리카_ 2020. 11. 5.
728x90
반응형

[ annoation이 나온 배경 ]

메타 데이터 (meta-data)
: 데이터의 데이터 

ex) 택배 상자위에 붙어 있는 택배 안 내용물에 대한 상품 정보를 생각하면 된다!

 

메타 데이터설정정보의 역할을 하고 이는 xml에 기재해둔다.

⇒ 즉, xml은 설정정보를 처리하며, 이를 메타데이터라고 부른다.

 

그런데 점점 설정정보가 많아지며, xml에 기재하기 복잡해졌다. (xml에 모두 기재하기는 방대해졌다.)

이를 해결하기 위해 나온 기술이 'annotaiton(어노테이션)'이다.

 

  xml annotation (어노테이션)
  메타데이터 설정정보를 저장하기 위해 쓰인다.
  코드와 설정을 분리 코드에 설정을 명시
  이후에 변경 가능한 것일 때 xml 방식 사용 초기에 설정하여 변경하지 않는 것은 annotaion 방식 사용
  유지보수성에 초점 생상성에 초점

annotation(어노테이션)

주석이 선언적 프로그래밍 모델을 지원하는 기술

 

즉, 의미있는 주석으로, 컴파일과 런타임(실행)에 영향을 준다.

⇒ Annotaion(ex. @Controller)은 컴파일과 런타임 시에 영향을 주는 주석이다


Spring Annotation

→ 설정 정보의 역할

 

> Spring Configuration(스프링 설정) 방법

→ XML + Annoataion + properties + Java Config

 

> Spring IOC Annotation 종류

  1. @Component 컴포넌트 계열 어노테이션 : 스프링 컨테이너에 해당 클래스의 객체를 생성하도록 명시
    -  @Repository : 영속성 계층에서 사용 (ex. MemerDAO) - 데이터 연동 로직
    -  @Service : 비즈니스(서비스) 계층에서 사용 (ex. MemberService) - 비즈니스 로직 
    -  @Controller : 프레젠테이션 계층에서 사용 (ex. MemberController)
    -  @Component : 모든 컴포넌트에 대한 제너릭 스테레오 타입 
                                        - 위 세가지 경우에 해당하지 않는 기타 자원 클래스에 사용 (ex. IOC/DI다 되지만 세밀한 제어X)

  2. @DI(Dependency Injection) 계열 어노테이션 : 스프링 컨테이너로부터 의존성(의존대상객체)를 주입받고자 할 때 사용
    - @AutoWired : 의존 대상 객체를 타입으로 검색해 주입
                                   (단, 동일한 인터페이스의 구현 객체가 여러 개 있을 경우 Exception 발생
                                      - 이를 해소하기 위해 @Quelifier("bean name")이 필요 )
    - @Resouce : 의존 대상 객체를 타입으로 검색 + name을 통해 주입 - 주로 많이 사용!
                                (추가적으로 @Resource(name="beanId")를 명시하면 bean id로 검색해 주입)

< Component 계열의 Annotation >

 


maven pom 설정

 

/pom.xml

<dependencies>
  <!-- Spring Framework -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.14.RELEASE</version>
  </dependency>
</dependencies>

Spring configure 설정

 

* namespace에서 component를 체크해준다!

<context:component-scan base-package="org.kosta">

 

<context:component-scan>은 base-package에서 설정한 "org.kosta"의 하위 패키지의 모든 클래스를 탐색해서,

1) 컴포넌트 계열의 어노테이션(@Component, @Repository, @Service, @Controller) 이 명시된 클래스들을 객체로 만든다.

2) DI 계열 어노테이션이 명시된 대상에 대해 해당 객체를 주입하는 역할을 한다.

 

/spring-config.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"
	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-4.3.xsd">
	
	<!-- 
		<context:component-scan>은 base-package에서 설정한
		 "org.kosta"의 하위 패키지의 모든 클래스를 탐색해서,
		컴포넌트 계열의 어노테이션(@Component, @Repository, @Service, @Controller)이
		명시된 클래스들을 객체로 만든다.
	 -->
	<context:component-scan base-package="org.kosta"></context:component-scan>

</beans>

Model

@Component 계열 annotation

@DI(Dependency Injection) 계열 어노테이션

 

 

@Repository 

- 영속성 계층에 적용하는 컴포넌트 계열 어노테이션

 

/ProductDAO.java <<interface>>

package org.kosta.model;

public interface ProductDAO {
	public void register(String info);
	
}

 

/ProductDAOImpl.java

package org.kosta.model;

import org.springframework.stereotype.Repository;

/*@Repository
 * : @Component 계열의 어노테이션
 *  - 영속성 계층에 적용하는 컴포넌트 계열 어노테이션
 */
@Repository
public class ProductDAOImpl implements ProductDAO{
	
	@Override //오버라이드 규칙은 컴파일 시 체크하는 어노테이션
	public void register(String info) {
		System.out.println("ProductDAOImpl register");
	}
}

 

/ProductDAOImplVer2.java

package org.kosta.model;

import org.springframework.stereotype.Repository;

@Repository
public class ProductDAOImplVer2 implements ProductDAO{
	
	@Override //오버라이드 규칙은 컴파일 시 체크하는 어노테이션
	public void register(String info) {
		System.out.println("ProductDAOImpl register");
	}
}

@Service

- 비즈니스 계층(서비스 계층)에 적용하는 어노테이션

 

/ProductService.java <<interface>>

package org.kosta.model;

public interface ProductService {
	public void register(String info);
}

 

@Autowired : Spring Container로부터 아래 객체를 주입받음 (생성자DI와 같은 역할)

BUT ! Autrowired 어노테이션은 타입으로 검색해 주입하므로,

동일한 인터페이스 타입의 구현체가 여러개일 경우에는 적합하지 않다. 그래서 대체제로 @Resouce를 사용한다.

@Resource (name="id") : 직접 구현체 id를 명시해 주입받는다.

 

/ProductServiceImpl.java

package org.kosta.model;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

/*
 * @Service
 *  : 컴포넌트 계열 어노테이션
 *  - 비즈니스 계층(서비스 계층)에 적용하는 어노테이션
 */
@Service
public class ProductServiceImpl implements ProductService{
	
	// @Autowired : Spring Container로부터 아래 객체를 주입받음 (생성자DI와 같은 역할)
	//@Autowired
	// 위 Autrowired 어노테이션은 타입으로 검색해 주입하므로,
	// 동일한 인터페이스 타입의 구현체가 여러개일 경우에는 적합하지 않다.
	@Resource(name = "productDAOImpl")
	private ProductDAO productDAO;
	
	@Override
	public void register(String info) {
		// -- 상품 등록에 관련한 처리 --
		productDAO.register(info);
	}

}

Test

/TestAnnotation.java

package test;

import org.kosta.model.ProductService;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAnnotation {
	public static void main(String[] args) {
		ClassPathXmlApplicationContext factory 
			= new ClassPathXmlApplicationContext("spring-config.xml");
		
		/*DL방식으로 객체 생성 여부 확인
		 * -> Component 방식 annotaion으로 생성된 빈의 id는
		 *    소문자로 시작하는 자신의 클래스명이 된다.
		 */
		
		// 1. repository(영속성 계층) 어노테이션 객체 반환
		System.out.println(factory.getBean("productDAOImpl"));
		//출력값 : org.kosta.model.ProductDAOImpl@371a67ec
		
		// 2. 서비스 계열 어노테이션 객체 반환
		System.out.println(factory.getBean("productServiceImpl"));
		//출력값 : org.kosta.model.ProductServiceImpl@5ed828d
		
		// 3. @Autowired된 비즈니스(서비스) 계층에 주입된 
		//    영속성 계층의 객체를 반환하여 함수 실행
		ProductService service 
			= (ProductService) factory.getBean("productServiceImpl");
		service.register("딸기"); 
		//출력값 : ProductDAOImpl register
		
		factory.close();
	}
}
 

 

ProductDAO dao = (ProductDAO) factory.getBean("productDAOImpl");

→ DL방식으로 객체 생성 여부 확인 

→ Component 방식 annotaion으로 생성된 빈의 id는 소문자로 시작하는 자신의 클래스명이 된다.

 

728x90
반응형