Spring 3일차

Shin·2023년 2월 22일
0

spring

목록 보기
3/8

Bean 을 문자열로 출력한다면?

  • console로도 출력하고, file 로도 출력하고, db출력하고...

Strategy pattern(전략패턴)

전략 패턴은 인터페이스를 사용해, 추상클래스를 사용한 상속은 아니지만, 마치 상속을 한 것과 비슷한 분리를 만들어내는 디자인 패턴이다.

클래스 다이어그램으로 그려졌듯이, Output 이라는 인터페이스를 구현한 FileOutputConsoleOutput 이라는 구현체가 있고,
MessageBean 이라는 인터페이스를 구현한 MessageBeanImpl 이라는 구현체가 있다.

MessageBeanImpl 구현체 내에는 Output 인터페이스를 인스턴스 필드로 받는데, 이 필드 데이터로 FileOutput 혹은 ConsoleOutput 구현체를 bean 으로 생성한 객체가 주입된다.

bean에 String 이 아닌 객체를 주입할 때에는

이 때, super() 와 같은 형식으로

하나의 클래스 내에서 인스턴스 필드로 또다른 객체를 받을 수도 있다.

그런데, 이렇게 xml 파일로 bean 들을 관리하다보면, 프로젝트의 크기가 커질수록 입력해야 할 내용들도 많아지고 번거로워 진다.

특히 c:employee-ref="bean_id" 와 같이, bean으로 생성된 객체를 주입할 경우 자동적으로 주입할 수 있도록 하는 속성이 존재한다.
그것이 바로 autowired 이다.

Auto-Wireing

자동주입(자동으로 의존 객체를 주입하는 기능) 기능이다.

명시적인 언급 없이도 Bean이 주입될 수 있다.

XML : 의존관계를 파악하는 것이 용이하지만, 프로젝트의 사이즈가 커질수록 양이 너무 많아지기 때문에 관리가 어려워진다.

그래서 이를 개선하기 위해 등장한 방식이 Auto-Wireing 방식이다.

Auto-Wireing 에는 3가지 방식이 있다.

1. XML 상에서 속성(autowire)을 이용하는 방법

<bean autowire="byName" />
autowire 속성 추가 시, bean의 식별자(bean의 id)를 가지고 주입하게 된다.

만약 TestBean 이라는 클래스 내부에 setData1() 이 존재하지 않거나 혹은 setData3() 이라는 setter 가 있는데 xml 내부의 bean iddata1 이라는 등, setter의 name 과 주입할 bean 의 id 가 일치하지 않는다면, autowire 로 주입이 이루어지지 않는다.

그렇다면 testBean 의 instance field 이름을 기준으로 찾는 것일까, 아니면 setter 의 인자 이름을 기준으로 찾는 것일까?

=> bean 의 Id와 instance field 의 식별자 이름이 일치한다면, 자동 주입이 된다.

2. XML 상에서 타입을 이용하는 방법

<bean autowire="byType" />
bean 의 클래스 타입을 가지고 주입하게 된다.

로그를 보면 동일한 getData1() 과 getData2() 를 통해 출력되는 객체 data1 과 data2 가 동일한 객체(primary=true 속성이 부여된 data1 bean 객체 ) 임을 알 수 있다.

2-2. 생성자를 이용하는 방법

  • 내부적으로는 byType 을 통하게 된다.

XML 파일 전체적으로 authwire 를 거는 방법

<xml> 태그의 속성 안에 default-autowire를 통해 모든 bean 주입에 대해 자동 주입을 설정할 수 있다.
만약 이 설정을 한 뒤, 자동 주입을 하지 않을 bean 이 있다면
authwire="no" 속성을 입력하면 된다.

3. 어노테이션을 이용하는 방법

@Autowired
private Object obj;

어노테이션을 가지고 주입할 때에는 내부적으로 "byType" 방식으로 주입한다.

📌 @Component

@Component 라는 어노테이션을 클래스에 입력하게 되면, 해당 클래스 자체를 bean 으로 등록한다.

이 클래스에 대한 정보에 applicationContext 에 저장되는 것이다. 이 클래스를 기반으로 bean 객체가 생성되어 주입된다.

@Component 로 bean 이 등록된다면, xml 파일에서 bean을 생성할 때 입력해야 했던 bean 의 id 값은 자동적으로 클래스의 이름으로 잡히게 된다. 카멜케이스에 의거해 첫글자는 소문자로!

혹은 @Component("id값 입력") 을 통해 id 값을 지정해줄 수도 있다.

Annotaion 설정을 이용하기 위해서는, XML에 특별한 code 를 넣어야 한다. 즉 xml 내부에 설정은 annotaion 으로 하겠다는 선언을 해주는 코드가 필요하다는 의미이다.

📌 @Autowired

자동으로 의존관계를 맺을 때 사용하는 annotation 이다.

사용이 가능한 케이스는 3가지가 있다.

  • 특정 필드에 붙일 수 있다.(가장 자주 쓰이는 방식)

  • constructor 에 붙일 수 있다.

  • method 에 붙일 수 있다.
    (일반적으로 setter 를 지칭하는데, 일반 method 에도 붙일 수는 있지만 자주 쓰이지는 않는다.)

@Autowired 로 주입하는 방식은 내부적으로 byType 형태로 이루어진다.

만약 같은 데이터 타입이 두 개 이상 bean 이 있으면 field 명 에 일치하는 것이 있는지, 혹은 method 의 parameter 이름 으로 일치하는 것이 있는지 확인한 후 주입을 하게 되는데, 이 과정을 거쳐서도 없다면 error 를 낸다.

byType 에 의해 Food 타입의 bean 객체를 1차적으로 검색
그러나 아래의 xml 파일에서 보면 Food 타입의 bean 객체는 두 개 존재한다.(favoriteFood, unFavoriteFood)
그래서 2차적으로 bean 객체의 id 와 현재 자동 주입하려는 필드의 식별자 를 비교해서 매칭되는 게 존재한다면 그 bean 객체를 주입한다.

context:component-scan base-package="package 주소" 를 통해 @Component 라는 어노테이션이 사용되는 지를 검사할 패키지를 입력해준다.

field 에 autowired 가 붙었다면
	1) bean 클래스 타입 == field 의 데이터 타입
	2) bean 의 id == field 의 식별자 이름

일반 메소드에 autowired 가 붙었다면
	bean 의 id == 메소드가 받는 파라미터의 이름

주의해야 할 점은 intelliJ 에 의해 자동완성으로 schema 를 추가하다보면 p 나 c 를 추가할 경우에는 큰 문제가 발생하지 않았지만 context 를 추가할 때에는 schemaLocation 에도 context 관련 내용을 추가해주어야 한다.

안그럴 경우 아래와 같은 error 를 내뱉는다.

📌 @Autowired(required=false) : 원래 bean에 객체를 자동 주입하는 것이 Autowired 이고, 주입할 bean 객체가 없다면 error 를 내는 것이 기본 값인데

required=false 라는 속성을 통해 만약 bean 객체가 없더라도 정상적으로 생성을 할 수 있도록 한다.

필드에 Autowired 를 걸어놓을 경우, 자동 주입을 할 때 setter 를 이용하지 않고 그대로 주입이 이루어진다. 즉 setter 를 거치지 않고 주입이 이루어진다.

birth 가 bean 으로 등록되어 있지 않을 경우 autowired 는 error 를 낸다.

하지만 autowired(required=false) 설정을 해준다면

birth 는 null 값으로 반환이 이루어진다.(즉 error 가 나지는 않는다.)

생성자는 여러 종류를 오버로딩 할 수 있지만, autowired 어노테이션은 오직 하나의 생성자에만 사용할 수 있다.

@Component 를 통해 빈 객체가 생성될 때에는 default 값으로 기본 생성자를 통해 생성이 되고, @Autowired 어노테이션이 붙은 생성자가 있다면 해당 생성자를 통해 빈 객체를 생성한다. 다만 이 경우, parameter 로 받게 되는 객체 역시 빈 객체로 등록되어 있어야 한다.

emp 를 parameter 로 받는 생성자를 autowired 어노테이션을 사용하자, 기본 생성자가 아니라 어노테이션이 붙은 생성자로 빈 객체가 생성되었다.

주의할 점으로 생성자에는 @Autuwired(required=false) 는 적용되지 않는다.
생성자의 parameter 로 들어오는 객체가 autowired 가 불가능할 경우 ( bean 객체로 등록이 안되어 있을 경우 )
오류가 발생한다.

즉, autowired 어노테이션이 붙은 생성자의 parameter 로 들어오는 객체는 bean 객체로 등록이 되어 있어야만 한다.

기본 생성자로 빈 객체를 생성 한 후 autowired 어노테이션이 설정된 인스턴스 필드와 맞는 타입/name 의 빈 객체를 찾아 객체를 주입한다.
다만 그 과정에서 setter 메소드를 거치는 것이 아니다.

📌 @Qualifier

@Autowired 어노테이션과 같이 사용되는 어노테이션이다.

Bean 을 이름을 이용해 주입할 때 사용한다.

📌 @Resource

@Autowired와 기능은 동일하다. 자동 주입을 해주는 것.
차이점은 @authwiredbyType 으로 주입하지만
@Resource 의 경우에는 byName 을 이용해 자동 주입이 이루어진다.

📌 @Scope

Bean 의 scope 를 지정해주는 어노테이션.
위치는 @Component 아래, 즉 class 단위로 사용이 이루어진다.

기본값은 singleton 이고, prototype 으로 명시하게 되면 Bean 객체가 요청에 따라 생성이 이루어진다.

0개의 댓글