테스트를 할 때는 데이터를 경계가 되는 값의 전후로 선택하는 것이 좋음
ex) 10 이면 9, 11 이런식으로
객체지향적인 코드 -> 다른 오브젝트의 데이터를 가져와서 작업하는 대신 그 데이터를 갖고있는 다른 오브젝트에게 작업을 해달라고 요청
여러 클래스에서 반복되는 값은 상수로 만들어두자.
트랜잭션 -> 더이상 나눌 수 없는 단위 작업 (원자성)
Connection 오브젝트를 통해 트랜잭션이 이루어짐.
기본적으로 DB작업을 수행한 후 자동 커밋이 되기 때문에
setAutoCommit(false) 후 rollback() or commit() 해야함.
JdbcTemplate 트랜잭션 저장소에 동기화된 Connection이 없으면 직접 커넥션을 생성한다.
Local Transaction -> 하나의 DB에 종속
Global Transaction -> 여러 DB가 함께하는 작업을 하나의 트랜잭션으로 만들 수 있음.
Java Transaction Api
추상화 -> 하위 시스템의 공통점을 뽑아내 분리하는 것.
하위 시스템이 뭔지 몰라도 일관된 방법으로 접근 가능'
트랜잭션 동기화
스프링의 트랜잭션 추상화 계층
트랜잭션 방법에서 독립적이게 됨(의존하지 않음)
JNDI -> 자바 애플리케이션을 외부 디렉터리 서비스에 연결
어떤 클래스든 스프링 빈으로 등록할 때 싱글톤으로 만들어져 여러 스레드에서 동시에 사용해도 괜찮은가를 먼저 검토해야함
단일 책임 원칙 -> 하나의 모듈은 한가지 책임만을 가져야 함
어떤 변경이 일어날 때 수정 대상이 명확해짐.
MailSender -> 스프링이 제공하는 메일 서비스 추상화 인터페이스
외부 리소스와 연동하는 대부분 작업은 추상화의 대상이 될 수 있음
테스트를 위해 테스트용 Object를 만들어 DI함(필요시)
Mock Object -> 테스트 오브젝트와 자신의 사이에서 일어나는 커뮤니케이션 내용을 저장해뒀다가 테스트 검증에 활용
스프링 3대 기반 기술 -> IoC/DI , 서비스 추상화, AOP
테스트를 고립시키자 -> 의존하는 오브젝트가 영향을 주지 못하도록 Mock오브젝트로 만들자
단위테스트 -> 테스트 대상 클래스를 목 오브젝트등의 테스트 대역을 이용해 의존 오브젝트나 외부의 리소스를 사용하지 않도록 고립시켜 테스트하는 것.
통합 테스트 -> 두개 이상의 성격이나 계층이 다른 오브젝트가
연동하도록 만들어 테스트하거나, 외부의 DB나 파일, 서비스 들의 리소스가 참여하는 테스트
Mockito 프레임워크 -> Mock 오브젝트를 매번 만드는 것은 번거로움. Mockito 프레임워크를 이용하면 편리함.
ArgumentCaptor -> 실제 목 오브젝트에 전달된 파라미터를 가져와 내용을 검증. 파라미터 내부 정보 확인.
Proxy
Target과 같은 인터페이스로 구현함
Proxy가 Target을 제어할 수 있는 위치에 있음
목적
클라이언트가 타깃에 접근하는 방법은 제어(프록시 패턴)
타깃에 부가적인 기능 부여(데코레이터 패턴)
데코레이터 패턴 -> 인터페이스를 통해 타겟에 위임하는 방식
타깃에 부가적인 기능을 런타임시에 다이내믹하게 부여해주기 위해 프록시를 사용하는 패턴.
한 인터페이스, 한 타겟에 여러 프록시 사용 가능
ex) InputStream, OutputStream
프록시 패턴 -> 타겟의 기능을 확장하지는 않음.
클라이언트가 타깃에 접근하는 방식을 변경.
위 두개의 문제 -> 코드 작성이 번거롭고 프록시 내에 코드의 중복이 발생할 확률이 높음
리플렉션 -> 자바의 코드 자체를 추상화해서 접근하도록 만든 것.
모든 클래스에는 클래스 자체의 구성 정보를 담은 Class 타입의 오브젝트를 하나씩 갖고있음 (.class, getClass())
Method 오브젝트를 이용해 메서드를 호출시킬 수 잇음
다이내믹 프록시
프록시 팩토리에 의해 런타임 시 다이내믹하게 만들어지는 오브젝트.
타겟의 인터페이스와 같은 타입으로 만들어짐.
프록시 팩토리에 인터페이스 정보만 주면 자동으로 그 구현체를 만들어줌.
다이내믹 프록시 오브젝트는 클라이언트의 모든 요청을 리플렉션 정보로 변환해서 InvocationHandler 구현체의 invoke() 메서드로 넘김
InvocationHandler 구현체를 만들고
Proxy.newInstanceProxy(클래스로더, 인터페이스, InvocationHandler)로 다이내믹 프록시 생성하여 사용