애플리케이션에서 사용자의 요구 사항에 따라 클래스 기능을 변경하거나 다른 클래스 기능으로 대체해야 하는 경우가 생김 -> 대체를 수월하게 할 수 있게 도입된 기능이 의존성 주입과 제어 역전임
의존성 주입하기
- 기존 : 사용할 클래스와 사용될 클래스의 관계는 개발자에 의해 직접 코드에서 부여됨(사용할 클래스의 생성자 호출)
- 의존성 주입 : 컨테이너가 연관 관계를 직접 규정하는 것 -> loosely coupled(약한 결합. 직접적인 연관 관계가 발생하지 않으므로 각 클래스들의 변경이 자유로워지는 것)
- 각 클래스들의 연관 관계를 스프링 프레임워크에서의 설정을 통해 맺어줌으로써 클래스들이 연관 관계를 갖지 않게 구현됨
의존성 주입을 사용하기 전 게시판 기능
클래스의 기능을 일일히 변경해 주어야 하기 때문에 BoardDAO, BoardService의 기능을 변경해야 함
->프로젝트 규모가 커지면 자바 코드에서 직접 객체를 생성해서 사용하는 것(tightly coupled)은 복잡한 문제를 일으킬 수 있음
인터페이스를 적용한 게시판 기능
- 각각의 클래스가 인터페이스를 구현하는 구조를 이름
- BoardDAO 인터페이스를 구현한 또 다른 MySqlDAOImpl 클래스를 구현한 후 ServiceImpl에서 사용하면 됨 -> 이후 각 클래스의 객체를 사용할 때는 인터페이스 타입으로 선언한 참조 변수로 접근해서 사용하면 됨
- 인터페이스를 사용하면 의존 관계가 전보다는 더 약해지긴 했지만, 여전히 소스 코드에서 직접 수정해야 함
의존성 주입을 적용한 게시판 기능
- XML이나 어노테이션을 이용해 객체를 주입하여 객체들의 의존 관계를 맺어주면 됨
- DI(의존성 주입)를 사용하여 각 객체들 간의 의존 관계를 최소화함으로써 코드를 단순화하고 유지보수를 쉽게 할 수 있음
- 일반적으로 스프링에서는 IoC의 기능을 DI로 구현
- DI는 객체의 생성, 소멸, 의존 관계를 XML이나 어노테이션 설정을 통해 경량 컨테이너에 해당하는 스프링 프레임워크가 제어함
- BoardServiceImpl 클래스는 의존하는 BoardDAOImpl 객체를 전달받기 위해 new 키워드를 사용해 객체를 생성하지 않고 생성자를 호출할 때 외부에서 객체를 주입 받아 사용
public class BoardServiceImpl implements BoardService{
private BoardDAO boardDAO;
public BoardServiceImpl(BoardDAO boardDAO){
this.boardDAO = boardDAO;
}
...
}
의존성 주입 방법
의존성 주입의 장점
- 클래스들 간의 의존 관계를 최소화하여 코드를 단순화할 수 있음
- 애플리케이션을 더 쉽게 유지 및 관리할 수 있음
- 기존 구현 방법은 개발자가 직접 코드 안에서 객체의 생성과 소멸을 제어했지만 의존성 주입은 객체의 생성, 소멸과 객체 간의 의존 관계를 컨테이너가 제어함
Dependency Injection(DI)
- 스프링에서 의존(dependency)하는 객체를 컨테이너 실행 시 주입(injection)하는 것
- 각 클래스 객체를 bean이라고 부름 : 의존 관계를 설정하는 외부 XML(spring 설정 파일) 파일에서 각각의 객체를 < bean > 태그로 표시하기 때문
< bean >태그의 속성
속성 이름 | 설명 |
---|
id | 빈 객체의 고유 이름. 빈 id를 이용해 빈에 접근 |
name | 객체의 별칭 |
class | 생성할 클래스. 패키지 이름까지 입력해야 함 |
constructor-arg | 생성자를 이용해 값을 주입할 때 사용 |
property | setter를 이용해 값을 주입할 때 사용 |
스프링에서 AOP 기능 사용하기
용어 | 설명 |
---|
aspect | 구현하고자 하는 보조 기능을 의미 |
advice | aspect의 실제 구현체(클래스)를 의미. 메소드 호출을 기준으로 여러 시점에서 실행됨 |
joinpoint | advice를 적용하는 지점을 의미. 스프링은 method 결합점만 제공 |
pointcut | advice가 적용되는 대상을 지정. 패키지이름/클래스이름/메소드이름을 정규식으로 지정하여 사용 |
target | advice가 적용되는 클래스를 의미 |
weaving | advice를 주기능에 적용하는 것을 의미 |
스프링 API를 이용한 AOP 기능 구현 과정
- 타깃(target) 클래스를 지정
- 어드비아스(advice) 클래스를 지정
- 설정 파일에서 포인트컷(Pointcut)을 설정
- 설정 파일에서 어드바이스와 포인트컷을 결합하는 어드바이저 설정
- 설정 파일에서 스프링의 ProxyFactoryBean 클래스를 이용해 타깃에 어드바이스를 설정
- getBean() 메소드로 빈 객체에 접근해 사용
인터페이스 | 추상메소드 | 설명 |
---|
MethodBeforeAdvice | void before(Method method, Object[] args, Object target) throws Throwable | 해당 메소드가 실행되기 전 실행 |