반응형
01. spring 컨테이너가 컴포넌트로 만들어주는 어노테이션 (부모 - 자식)
02. 의존성 주입을 위해 사용하는 어노테이션
03. 💖Spring Bean Configuration File
[05-4.diAnnotation.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.xsd>">
<!-- base-package 속성값으로 설정된 xyz.itwill05.di 패키지 내 클래스들 중
어노테이션을 찾아 Spring 컨테이너가 컴포넌트로 만들어줄게요~ -->
<context:component-scan base-package="xyz.itwill05.di"/>
</beans>
04. DAO클래스 - 포함(의존) : 부
(자식) AnnotationStudentJdbcDAO클래스 : Spring Bean이 된 DAO 클래스
package xyz.itwill05.di;
import java.util.List;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
//@Component : 클래스를 스프링 컨테이너가 관리할 수 있는 Spring Bean으로 등록하기 위한 어노테이션
// => 클래스의 이름을 beanName으로 자동 설정 - 클래스의 이름에서 첫문자는 소문자로 변환
// => @Component value 속성을 사용하여 beanName 변경 가능(단, beanName 중복 절대 불가능) - 다른 속성이 없는 경우 속성값만 설정 가능
//@Component
//@Repository : [DAO클래스]를 스프링 컨테이너가 관리할 수 있는 Spring Bean으로 등록하기 위한 어노테이션
//=> 클래스의 이름을 beanName으로 자동 설정하지만 value 속성으로 beanName 변경 가능
//@Repository을 사용하는 이유
//1. 이 스프링 빈이 어떤 역할을 하는지 좀 더 쉽게 구분하기 위해 사용함 즉, 다른 클래스들과 역할을 명확히 구분할 수 있음
//2. 메소드가 더 많음 - 트랜잭션을 이용하는 메소드가 있음 : 트랜잭션 매니저에 의해 메소드가 관리됨
//@Primary : 의존성을 주입하기 위한 우선권을 제공하기 위한 어노테이션
// => 동일 자료형의 클래스에 @Primary 어노테이션을 사용한 경우 의존성 주입 실패
//@Primary
//@Repository("studentDAO")
@Repository
public class AnnotationStudentJdbcDAO implements StudentDAO {
public AnnotationStudentJdbcDAO() {
System.out.println("### AnnotationStudentJdbcDAO 클래스의 기본 생성자 호출 ###");
}
@Override
public int insertStudent(Student student) {
System.out.println("*** AnnotationStudentJdbcDAO 클래스의 insertStudent(Student student) 메소드 호출 ***");
return 0;
}
@Override
public int updateStudent(Student student) {
System.out.println("*** AnnotationStudentJdbcDAO 클래스의 updateStudent(Student student) 메소드 호출 ***");
return 0;
}
@Override
public int deleteStudent(int num) {
System.out.println("*** AnnotationStudentJdbcDAO 클래스의 deleteStudent(int num) 메소드 호출 ***");
return 0;
}
@Override
public Student selectStudent(int num) {
System.out.println("*** AnnotationStudentJdbcDAO 클래스의 selectStudent(int num) 메소드 호출 ***");
return null;
}
@Override
public List<Student> selectStudentList() {
System.out.println("*** AnnotationStudentJdbcDAO 클래스의 selectStudentList() 메소드 호출 ***");
return null;
}
}
(자식) AnnotationStudentMyBatisDAO클래스 : Spring Bean이 된 DAO 클래스
package xyz.itwill05.di;
import java.util.List;
import org.springframework.stereotype.Repository;
@Repository
public class AnnotationStudentMyBatisDAO implements StudentDAO {
public AnnotationStudentMyBatisDAO() {
System.out.println("### AnnotationStudentMyBatisDAO 클래스의 기본 생성자 호출 ###");
}
@Override
public int insertStudent(Student student) {
System.out.println("*** AnnotationStudentMyBatisDAO 클래스의 insertStudent(Student student) 메소드 호출 ***");
return 0;
}
@Override
public int updateStudent(Student student) {
System.out.println("*** AnnotationStudentMyBatisDAO 클래스의 updateStudent(Student student) 메소드 호출 ***");
return 0;
}
@Override
public int deleteStudent(int num) {
System.out.println("*** AnnotationStudentMyBatisDAO 클래스의 deleteStudent(int num) 메소드 호출 ***");
return 0;
}
@Override
public Student selectStudent(int num) {
System.out.println("*** AnnotationStudentMyBatisDAO 클래스의 selectStudent(int num) 메소드 호출 ***");
return null;
}
@Override
public List<Student> selectStudentList() {
System.out.println("*** AnnotationStudentMyBatisDAO 클래스의 selectStudentList() 메소드 호출 ***");
return null;
}
}
05. Service클래스 - 포함(의존) : 주
(자식) AnnotationStudentServiceImpl클래스 : Spring Bean이 된 서비스 클래스
package xyz.itwill05.di;
import java.util.List;
import javax.inject.Inject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.ImportResource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
//@Component("studentService")
//@Service : [Service클래스]를 스프링 컨테이너가 관리할 수 있는 Spring Bean으로 등록하기 위한 어노테이션
//=> 클래스의 이름을 beanName으로 자동 설정하지만 value 속성으로 beanName 변경 가능
//@Service을 사용하는 이유
//1. 이 스프링 빈이 어떤 역할을 하는지 좀 더 쉽게 구분하기 위해 사용함
//=> 즉, 다른 클래스들과 역할을 명확히 구분할 수 있음
//2. 메소드가 더 많음 - 예외처리를 수월하게 할 수 있음
@Service("studentService")
public class AnnotationStudentServiceImpl implements StudentService{
//@Autowired : 스프링 컨테이너로부터 Spring Bean을 제공받아 필드에 저장하여 의존관계를 자동으로 구현하기 위한 어노테이션
//=> 의존성 주입을 위해 필드에 사용하는 어노테이션 - "선언된 필드마다" 어노테이션 설정
//=> bean 엘리먼트에서 autowire 속성값을 [byType]으로 설정한 것과 같은 방법으로 의존성 주입 - Setter Injection
//=> Setter메소드를 이용하여 의존관계를 설정하지만 Setter 메소드를 작성하지 않아도 의존성 주입
//문제점) 필드의 자료형과 같은 자료형의 Spring Bean이 2개 이상 존재할 경우 의존성 주입 실패 - NoSuchBeanDefinitionException 예외 발생
@Autowired
//해결법-1) 필드의 자료형과 같은 자료형의 Spring Bean이 2개 이상 존재할 경우 필드에 저장될
//Spring Bean의 식별자(beanName)를 필드명과 같은 이름으로 변경
//=> @Autowire 어노테이션은 필드의 자료형과 같은 자료형의 Spring Bean이 2개 이상 존재하는
//경우 bean 엘리먼트에서 autowire 속성값을 [byName]으로 설정한 것과 같은 방법으로 의존성 주입
//해결법-2) 필드의 자료형과 같은 자료형의 Spring Bean이 2개 이상 존재할 경우 필드에 저장될
//Spring Bean에 대한 클래스에 [@Primary 어노테이션]을 사용하여 작성
//해결법-3) 필드에 [@Qualifier 어노테이션]을 사용하여 의존성 주입을 위한 Spring Bean 지정
//=> [@Primary 어노테이션]과 [@Qualifier 어노테이션]이 같이 설정된 경우
//[@Qualifier 어노테이션]으로 의존성 주입
//@Qualifier : 필드와 의존관계가 설정될 Spring Bean를 직접 지정하기 위한 어노테이션
//=> @Autowired 어노테이션에 종속된 어노테이션
//=> 동일한 자료형이 여러개일 경우 사용
//value 속성 : 의존관계를 설정하기 위한 Spring Bean의 식별자(beanName)를 속성값으로 설정
//=> 다른 속성이 없는 경우 속성값만 설정 가능
//@Qualifier("annotationStudentJdbcDAO")
@Qualifier("annotationStudentMyBatisDAO")
private StudentDAO studentDAO;
//@Autowired 어노테이션 대신 [@Resource 어노테이션] 또는 [@Inject 어노테이션]을 사용하여 의존성 주입 가능
// => @Autowired 어노테이션은 Spring Framework의 라이브러리로 제공하는 어노테이션이지만,
//@Resource 어노테이션 또는 @Inject 어노테이션은 JDK 라이브러리로 제공하는 어노테이션
// => @Resource 어노테이션 또는 @Inject 어노테이션은 다른 Framework에서 사용 가능
//@Resource 어노테이션 : bean 엘리먼트에서 autowire 속성값을 [byName]으로 설정한 것과 같은 방법으로 의존성 주입하는 어노테이션
//@Inject 어노테이션 : bean 엘리먼트에서 autowire 속성값을 [byType]으로 설정한 것과 같은 방법으로 의존성 주입하는 어노테이션
//생성자
public AnnotationStudentServiceImpl() {
System.out.println("### AnnotationStudentServiceImpl 클래스의 기본 생성자 호출 ###");
}
//Service클래스의 메소드
@Override
public void addStudent(Student student) {
System.out.println("*** AnnotationStudentServiceImpl 클래스의 addStudent(Student student) 메소드 호출 ***");
studentDAO.insertStudent(student);
}
@Override
public void modifyStudent(Student student) {
System.out.println("*** AnnotationStudentServiceImpl 클래스의 modifyStudent(Student student) 메소드 호출 ***");
studentDAO.updateStudent(student);
}
@Override
public void removeStudent(int num) {
System.out.println("*** AnnotationStudentServiceImpl 클래스의 removeStudent(int num) 메소드 호출 ***");
studentDAO.deleteStudent(num);
}
@Override
public Student getStudent(int num) {
System.out.println("*** AnnotationStudentServiceImpl 클래스의 getStudent(int num) 메소드 호출 ***");
studentDAO.selectStudent(num);
return null;
}
@Override
public List<Student> getStudentList() {
System.out.println("*** AnnotationStudentServiceImpl 클래스의 getStudentList() 메소드 호출 ***");
studentDAO.selectStudentList();
return null;
}
}
06. 요청처리
AnnotationStudentApp.java
package xyz.itwill05.di;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AnnotationStudentApp {
public static void main(String[] args) {
System.out.println("================== Spring Container 초기화 전 ==================");
ApplicationContext context=new ClassPathXmlApplicationContext("05-4_diAnnotation.xml");
System.out.println("================== Spring Container 초기화 후 ==================");
StudentService service=context.getBean("studentService",StudentService.class);
service.addStudent(null);
System.out.println("================================================================");
((ClassPathXmlApplicationContext)context).close();
}
}
반응형