10강 - 생성자 DI
Exam exam = new NewlecExam(30, 40, 40, 50); 을 xml파일에서는 필드의 순서대로 넣어주면 된다.
(반드시 NewlectExam 클래스에 생성자(디폴트 생성자 아닌 매개변수 있는 생성자)를 만들어준 상태에서 하기!!)
=> bean객체(NewlectExam클래스의 exam 객체)를 생성시 값 할당
<bean id="exam" class="spring.di.entity.NewlecExam" >
<constructor-arg value="30" /> //kor
<constructor-arg value="40" /> //eng
<constructor-arg value="40" /> //math
<constructor-arg value="50" /> //com
</bean>
위와 같이 넣으면 어떤 필드값에 값이 할당 되는지 헷갈릴 수 있다.
case1) 필드 순서를 나타내는 index값을 넣어줌으로써 헷갈리는 것을 해결할 수 있다.
<bean id="exam" class="spring.di.entity.NewlecExam">
<constructor-arg index="0" value="10" /> //kor
<constructor-arg index="1" value="30" /> //eng
<contstructor-arg index="3" value="50" /> //com
<constructor-arg index="2" value="10" /> //math
</bean>
case2) 필드명을 나타내는 name값을 넣어줌으로써 해결할 수 있다.
<bean id="exam" class="spring.di.entity.NewlecExam">
<constructor-arg name="kor" value="10" />
<constructor-arg name="eng" value="30" />
<constructor-arg name="com" value="50" />
<constructor-arg name="math" value="10" />
</bean>
예외 상황 발생 ) 필드명은 같은데 필드 타입은 다른 상황인경우에는 어떻게 지정해야할까?
==> 필드값을 set할때 type을 지정할 수 있다.
위와 같이 속성을 설정하는데 너무 길다는 문제점이 발생!!!!!
==> 한줄로 속성 설정을 처리하는 방법
p:kor="10" 을 쓰려고 하니 p:kor="10" 을 처리하는 처리기를 xml파일에 불러와야한다.
※ 네임스페이스를 쓰는 이유 <namespace:bean> </namespace:bean>
1. 네임스페이스를 쓴 태그는 특정한 처리기에 의해 실행되기 위함
2. 태그의 이름을 식별하기 위해
ex.
<홍길동:bean> </홍길동:bean>
<김길동:bean> </김길동:bean>
==> 처리기에서 홍길동을 불렀을때는 김길동은 쳐다보지 않고 홍길동만 처리기에 의해 실행됨
위에서도 역시 xmln:p = "...." 로 네임스페이스를 p로 설정하였기에
<bean id="exam" class="spring.di.entity.NewlecExam" p:kor="10" p:eng="10" p:com="10" p:math="10" /> 으로
p를 호출했을때 위의 xmls:p = "..." 가 실행되어 처리할 수 있게 된다.
11강 - 콜렉션 생성과 목록 DI
List<Exam> exams = new ArrayList<>();
exams.add(new NewlecExam(1, 1, 1, 1));
for(Exam e : exams){
System.out.println(e);
}
위의 내용을 클래스 파일에서가 아닌 xml파일에서는 어떻게 만들까?
Step1) ArrayList 객체 만들기
[class 파일]
List<Exam> exams = new ArrayList<>();
[xml 파일]
<bean id="exams" class="java.util.ArrayList" />
만든 exams 객체를 사용하려면,
List<Exam> exams = (List<Exam>) context.getBean("exams");
Step2)
ArrayList 생성할때 Collection 객체를 생성자에 넣을 수 있다.
[class 파일]
exams.add(new NewlecExam(1,1,1,1));
[xml 파일]
생성자에서 List라는 Collection을 넣어준다.
* List에 NewlectExam(exam)객체를 넣어주는 방법
case1) 객체를 직접 생성하는 방법
<bean class="spring.di.entity.NewlecExam" p:kor="1" p:eng="1" p:com="1" p:math="1" />
case2) xml파일에서 만들었던 객체를 가져오는 방법
<ref bean="exam" />
//exam 객체(bean)을 참조(ref)한다.
ex.
<bean id="exams" class="java.util.ArrayList">
<constructor-arg>
<list>
<bean class="spring.di.entity.NewlectExam" p:kor="1" p:eng="1" p:com="1" p:math="1" />
<ref bean="exam" />
</list>
</constructor-arg>
</bean>
위와 같이 컬렉션을 가진 ArrayList를 만드는 것이 아니라
<list>
<bean class="spring.di.entity.NewlecExam" p:kor="1" p:eng="1" p:com="1" p:math="1" />
<ref bean="exam"/>
</list>
이것 자체가 ArrayList에 전달되는 Collection임으로 Collection을 개별적으로 따로 만드는 방법은 없을까?
=> 가능하다!
Step1) util이라는 namespace 추가
<util:list> </util:list> 를 쓸 수 있게 된다.
Step2) 컬렉션의 종류를 list-class="리스트 종류" 에 정의하기
ex. ArrayList 컬렉션 사용 예)
<util:list list-class="java.util.ArrayList"> //ArrayList의 객체를 만들겠다.
<bean class="spring.di.entity.NewlecExam" p:kor="1" p:eng="1" p:com="1" p:math="1" />
<ref bean="exam" />
</util:list>
Step3) 만든 ArrayList를 가져다 쓰기 위해 id값 정의하기
<util:list id="exams" list-class="java.util.ArrayList">
<bean class="spring.di.entity.NewlecExam" p:kor="1" p:eng="1" p:com="1" p:math="1" />
<ref bean="exam" />
</util:list>
12강 - 어노테이션을 이용할 때의 장점과 @Autowired를 이용한 DI해보기
@Autowired 어노테이션
현재 InlineExamConsole 클래스의 console 객체가 exam 객체를 injection 하는 부분을 xml파일로 설정한 것이다.
setter에서 사용하는 속성 또는 setter 에다가 @Autowired 라는 키워드를 붙여주면 xml파일 설정을 안해도 된다.
@Autowired를 사용하면 Spring은 어떤 프로세스로 Setter을 설정할까?
Step1) console객체를 만들때 InlineExamConsole 클래스 파일을 쭉 읽는다.
<bean id="console" class="spring.di.ui.InlineExamConsole">
.....
</bean>
Step2) InlineExamConsole 클래스 파일에서 @Autowired 라고 붙어진 setter을 찾게 된다.
@Autowired
@Override
public void setExam(Exam exam){
this.exam = exam;
}
==> 자동으로 객체를 연결해달라는 의미
단! 주의!!!!!!
Spring에서 알아서 @Autowired를 찾는게 아니고 xml파일에서 bean객체를 설정할때
@Autowired를 찾아서 세팅해주라는 키워드를 넣어주어야한다.
※ context라는 네임 스페이스가 필요!! (위에서 namespace를 추가했던 방법대로 똑같이 추가하기)
<context:annotation-config /> 을 xml파일 상단에 적어줌으로써 bean객체들은 어노테이션 객체를 갖고 있다 는 의미
==> bean객체 중에 어노테이션 객체가 있으니 찾아서 세팅해주세요!!
13강 - @Autowired의 동작방식 이해와 @Qualifier 사용하기
번호 순서대로 1 -> 2 -> 3 으로 객체를 생성하고 Injection을 한다.
그런데 1번에서 @Autowired를 찾을때 어떤 기준으로 찾을까?
클래스 타입으로 찾을까? 변수명으로 찾을까?
TEST1) 변수명을 바꿔보자(id="exam" ~> id = "exam1")
<bean id="exam1" class="spring.di.entity.NewlecExam" p:kor="10" p:eng="10" p:com="10" p:math="10" />
==> 결과가 잘 나온다.
TEST2) 변수명을 없애보자!
<bean class="spring.di.entity.NewlecExam" p:kor="10" p:eng="10" p:com="10" p:math="10" />
==> 결과가 잘 안나온다.
결론적으로!!
변수명으로 찾는것이 아니라 클래스타입으로 찾는다는 것을 알 수 있다.
@Autowired
@Override
public void setExam(Exam exam){
this.exam = exam;
}
에서 매개변수 'Exam" 타입을 찾아서 자동으로 할당 해주는 것
Spring은
NewlecExam은 Exam의 interface를 구현한 것임으로 생성된 NewlecExam의 bean 객체를 매개변수로 넣어준다.
만약 객체 아이디는 없고
<bean class="spring.di.entity.NewlecExam" p:kor="10" p:eng="10" p:com="10" p:math="10" />
<bean class="spring.di.entity.NewlecExam" p:kor="20" p:eng="20" p:com="20" p:math="20" />
필드값이 다른 똑같은 객체가 두개 생성한 상황에서는 어떻게 Autowired를 할까?
TEST1) 하나의 bean객체를 설정하는 id값을 setter매개변수 명과 같은 이름으로 객체를 생성하면 어떨까?
<bean id="exam" class="spring.di.entity.NewlecExam" p:kor="10" p:eng="10" p:com="10" p:math="10" />
<bean class="spring.di.entity.NewlecExam" p:kor="20" p:eng="20" p:com="20" p:math="20" />
@Autowired
@Override
public void setExam(Exam exam){
this.exam = exam;
}
==> 결과가 잘 나온다.
bean객체의 id값과 setter 매개변수명과 같은 이름으로 하니까 같은 이름의 bean객체가 Autowired 된다.
TEST2) bean객체의 id값을 "exam1" "exam2" 로 가질때 실행이 될까?
<bean id="exam1" class="spring.di.entity.NewlecExam" p:kor="10" p:eng="10" p:com="10" p:math="10" />
<bean id="exam2" class="spring.di.entity.NewlecExam" p:kor="20" p:eng="20" p:com="20" p:math="20" />
==> 결과가 잘 안나온다. 이름이 달라서 바인딩이 되지 않는다
그러면 bean 객체의 id값에 따라 setter 메서드의 매개변수 명을 계속 바꿔주어야 하나?
==> 이때 나온게 @Qualifier("bean 객체 id 값");
@Autowired
@Qualifier("exam2") //"exam2객체를 바인딩한다"
@Override
public void setExam(Exam exam){
this.exam = exam;
}
14강 - @Autowired의 위치와 required 옵션
인잭션 방법 3가지
1) 필드 위 : 기본 생성자를 호출하면서 injection
==> 기본 생성자를 없을때는 에러메세지가 뜬다. 반드시 기본 생성자가 있어야한다.
@Autowired
@Qualifier("exam2")
private Exam exam;
2) 생성자(디폴트 생성자X) 위
@Autowired
@Qualifier("exam2")
public InlineExamConsole(Exam exam, Exam exam2){
this.exam = exam;
}
으로 쓰면 에러 표시가 뜬다.
이유는 생성자의 매개변수가 여러개일 수 도 있기 때문에 그것을 지정해주는데 명확히 해주어야하기 때문이다.
case1) 매개변수 1개일때
@Autowired
public InlineExamConsole(@Qualifier("exam1") Exam exam){
System.out.println("overloaded constructor");
this.exam = exam;
}
case2) 매개변수 1개 이상일때
@Autowired
public InlineExamConsole(@Qualifier("eam1") Exam exam1, @Qualifier("exam2") Exam exam2){
System.out.println("overloaded constructor");
this.exam1 = exam1;
this.exam2 = exam2;
}
3) setter 메서드 위 : setter함수가 호출되면서 injection
@Autowired
@Qualifier("exam2")
@Override
public void setExam(Exam exam){
this.exam = exam;
}
====== [required 옵션] ======
@Autowired
@Qualifier("exam1")
private Exam exam;
@Autowired를 세팅했을때 반드시 xml파일에 bean객체를 등록해야한다.(없으면 에러가 뜬다.)
그런데 필요에 따라 bean객체가 없어도 그냥 실행되게 하고 싶을때가 있다.
ex. exam객체가 null 일때는 디폴트 프린트를 출력해준다.
@Override
public void print() {
if(exam == null) {
System.out.printf("total is %d, avg is %f \n", 0, 0.0);
}
System.out.printf("total is %d, avg is %f \n", exam.total(), exam.avg());
}
==> 이럴때 required 옵션을 사용한다.
@Autowired(required = false) //xml파일에 exam1이라는 bean객체가 없어도 괜찮다.
@Qualifier("exam1")
private Exam exam;
15강 - 어노테이션을 이용한 객체 생성
객체 생성과 @Component
@Component 어노테이션을 이용하여 InlineExamConsole 객체를 등록한다.
==> 오류가 발생한다.
왜? Spirng에서 @Component 어노테이션을 읽으라고 명령을 하지 않았기 때문이다.
(이전 시간에 @Autowired 도 역시 단순히 어노테이션만 쓰면 Spring이 읽지 않는다.
xml파일에서 <context:annotation-config /> 를 설정해줌으로써 읽었다.)
<context:component-scan base-package="spring.di.ui" />
spring.di.ui 패키지에 가서 클래스들이 있을텐데 component 가 있는지 스캔해서 있으면 객체화 시켜라!
InlineExamConsole 클래스의 @Component 어노테이션을 스캔하면 @Autowired 도 자연스럽게 읽게 됨으로써 xml파일에 있던 <context:annotation-config /> 설정은 없애도 된다.
@Component(객체id) 를 지정해줌으로써 만든 객체의 id값을 정해준다.
ex.
@Component("console")
public class InlineExamConsole implements ExamConsole{
....
}
ExamConsole console = (ExamConsole) context.getBean("console");
*만약 여러 패키지 내의 클래스의 component를 스캔하려고 한다면
<context:component-scan base-package="spring.di.ui , spring.di.entity" /> 와 같이
콤마로 패키지를 추가하면 된다.
출처: 뉴렉쳐
www.youtube.com/watch?v=XtXHIDnzS9c&list=PLq8wAnVUcTFWxnsrMu5kS_jt_o8gpEiTR&index=1
'스프링 프레임워크' 카테고리의 다른 글
Spring MVC (스프링 웹 MVC) 1강 ~ 13강 (0) | 2021.03.19 |
---|---|
뉴렉처[스프링 프레임워크_AOP] 1강 ~8강 (2) | 2021.03.11 |
뉴렉처[스프링 프레임워크] 16강~17강 (0) | 2021.03.02 |
뉴렉처[스프링 프레임워크] 5강~9강 (0) | 2021.02.23 |
뉴렉처[스프링 프레임워크] 1강~4강 (0) | 2021.02.20 |