BeanFactory, ApplicationContext
BeanFactory와 ApplicationContext는 인터페이스이다.
BeanFactory 인터페이스는 객체 생성과 검색에 대한 기능을 정의함. (싱글톤/프로토타입 빈인지 확인하는 기능도 제공)
ApplicationContext는 BeanFactory를 상속한다.
메시지, 프로필/환경 변수 등을 처리할 수 있는 기능을 추가로 정의함.
ApplicationContext (또는 BeanFactory)는 빈 객체의 생성, 초기화, 의존 주입, 보관, 제거 등을 관리하고 있기 때문에 컨테이너 (Container)라고도 불린다. 스프링 컨테이너는 내부적으로 빈 객체와 빈 이름을 연결하는 정보를 갖는다.
@Configuration
스프링 설정 클래스를 의미함.
스프링을 사용하려면 스프링이 어떤 객체를 생성하고, 의존을 어떻게 주입할지 정의한 설정 정보를 작성해야 함.
설정 클래스를 만든 이후, 설정 클래스를 이용해서 컨테이너를 생성해야 함.
(객체를 생성하고 의존 객체를 주입하는 것은 스프링 컨테이너이기 때문)
스프링 프로젝트를 하다보면, 여러 Bean을 설정하게 된다.
설정하는 Bean의 개수가 증가하면, 영역별로 설정 파일을 나눠서 관리하는 것이 좋다.
> ApplicationContext ctx = new AnnotationConfigApplicationContext(AppCtx.class); // AppCtx : 설정 클래스
이후 아래와 같이 Container를 통해 사용할 객체를 구할 수 있다.
> A a = ctx.getBean("이름", 객체의 클래스)
@import 어노테이션을 통해, 두 개 이상의 설정 클래스도 지정할 수 있다.
DI (Dependency Injection)
Dependency
: 객체간의 의존을 의미
A 클래스가 B 클래스의 메서드를 실행할 때, A는 B에 의존한다. 라고 표현
위처럼 의존은 변경에 의해 영향을 받는 관계를 의미함.
예를 들어, B 클래스의 b 함수명이 바뀌는 경우, A 클래스 내부의 b 함수명도 변경되어야 함.
-> 이때, A 클래스 내부에서 B 클래스의 객체도 생성해야 하는데, 이때문에 유지 보수 관점에서 문제점을 유발함
-> 객체를 직접 생성하는 방법 대신 DI를 통해 의존 처리를 한다.
-> DI는 의존 객체를 직접 생성하는 대신 의존 객체를 전달 받는 역할을 한다. (생성자를 통해 객체 수령)
-> 생성자를 통해 객체를 수령하게 되면, 직접 생성자를 통해 객체를 만드는 방식에 비해 수정할 내용이 줄어든다.
예를 들어, dao 클래스가 있을 때 이를 확장한 newDao가 있다고 하자.
생성자를 통해 객체를 수령하게 되면, 생성자에 넘겨지는 객체만 새로 선언하면 되는데, 만약 내부에서 직접 생성을 통해 주입하고 있다면 모든 클래스 내부를 바꿔야 한다.
@Autowired
위의 DI를 잘 활용한 어노테이션이 @Autowired이다.
스프링의 자동 주입 기능을 위한 것이다.
클래스의 Field에 @Autowired annotation을 붙이게 되면, 컨테이너가 해당 타입의 bean을 찾아 필드에 할당한다.
@Autowired 타입에 해당하는 빈이 없으면 익셉션을 발생시킨다.
만약 자동 주입할 대상이 필수가 아닌 경우에는 (1) @Autowired(required = false)로 지정하면 된다.
Spring 버전 5부터는 @Autowired (required = false) 대신에 의존 주입 대상에 (2) Java 8의 Optional을 사용해도 된다.
또는 (3) Nullable 을 사용하면 됨. Nullable의 경우, 자동 주입할 빈이 존재하지 않아도 메서드가 호출됨.
Spring boot의 경우, bean의 의존 관계를 Configuration 코드에서 따로 설정하지 않더라도, 자동으로 객체를 주입해주는 기능이 있고, 현재는 그런 자동 주입을 기본으로 사용하는 추세이다.
Component Scan
컴포넌트 스캔은 스프링이 직접 클래스를 검색해서, Bean으로 등록해주는 기능.
설정 클래스에 bean으로 등록하지 않더라도 원하는 클래스를 Bean으로 등록할 수 있으므로, 설정 코드가 크게 줄어듬
@Component 라는 annotation이 붙는 경우 bean에는 클래스의 맨 앞글자만 소문자로 바뀌어서 bean으로 등록됨
@Component("원하는 이름") 의 형태로 bean에 등록할 수 있음
@Component 가 붙은 클래스를 bean으로 등록하려면, Configuration 클래스에서 @ComponentScan이 필요
> @ComponentScan(basePackages = {"scan이 필요한 패키지 이름"}, excludeFilters=)
과 같이 사용함.
<기본으로 scan이 되는 대상>
- org.springframework.stereotype 패키지
0) @Component
1) @Controller : Web MVC와 관련 있음
2) @Service
3) @Repository : DB 연동과 관련이 있음
4) @Aspect
5) @Configuration
AOP 프로그래밍 (aspectjweaver)
AOP의 핵심은, 공통 기능 구현과 핵심 기능 구현을 분리하는 것.
여러 객체에 공통으로 적용할 수 있는 기능을 분리해서, 재사용성을 높여주는 프로그래밍 기법
aspectjweaver 의존을 추가한다. (해당 모듈은 스프링이 AOP를 구현할 때 사용하는 모듈)
AOP 프로그래밍을 이해하기 위해서는 Proxy에 대해서 이해하기
- 핵심 기능의 실행은 다른 객체에 위임하고 부가적인 기능을 제공하는 객체를 따로 만든다.
Proxy 객체 : 주로 접근, 제어 관점에 초점이 맞춰져 있음.
Decorator 객체 : 기능 추가 및 확장에 초점이 맞춰져 있음.