본문 바로가기

Spring

6.5 스프링 AOP 작업의 목표 트랜잭션 코드를 깔끔하고 료과적으로 분리 트랜잭션 코드는 투명한 부가기능 형태로 제공 기존 설계와 코드에 영향을 주지 않음 6.5.1 자동 프록시 생성 대부분의 문제는 해결함 타깃 코드는 깔끔한 채로 남아있음 부가기능은 한 번만 만들어 모든 타깃과 메서드에 재사용 가능 타깃의 적용 메소드를 선정하는 방식도 독립적으로 작성 가능 남은 문제 부가기능이 타깃 오브젝트마다 새로 만들어짐 ProxyFactoryBean의 어드바이스를 통해 해결 타깃 오브젝트마다 거의 비슷한 내용의 ProxyFactoryBean 설정정보를 추가해야함 중복 문제의 접근 방법 DAO 바뀌는 부분과 바뀌지 않는 부분을 구분해서 분리 템플릿과 콜백, 클라이어트를 분리 프록시 클래스 코드 다이내믹 프록시라는 런타임 코드 자동생성..
6.4 스프링의 프록시 팩토리 빈 6.4.1 ProxyFactoryBean 스프링은 일관된 방법으로 프록시를 만들 수 있게 도와주는 추상 레이어를 제공 프록시 오브젝트를 생성해주는 기술을 추상화한 팩토리 빈을 제공 ProxyFactoryBean : 프록시를 생성해서 빈 오브젝트로 등록하게 해주는 팩토리 빈 순수하게 프록시 생성을 위한 작업만을 담당하고, 부가 기능은 별도의 빈에 둘 수 있음 MethodInterceptor 인터페이스를 구현하여 만듦 InvocationHandler의 invoke() 메소드는 타깃 오브젝트에 대한 정보를 제공하지 않음 MethodInterceptor의 invoke() 메소드는 타깃 오브젝트에 대한 정보까지 함께 제공받음 타깃 오브젝트에 상관없이 독립적으로 만들 수 있음 싱글톤 빈으로 등록 가능 학습 테스트 ..
6.3 다이내믹 프록시와 팩토리 빈 6.3.1 프록시와 프록시 패턴, 데코레이터 패턴 확장성을 고려한 기능의 분리 전형적인 전략 패턴 사용 가능 트랜잭션을 적용한다는 사실이 코드에 남아있음 적용 사실 자체의 분리가 필요 UserServiceTx 생성 후 UserServieImpl에 트랜잭션 관련 코드를 모두 제거 부가기능 분리 시 부가기능 외 나머지 모든 기능은 원래 핵심기능을 가진 클래스로 위임해주어야 함 부가기능의 사용 클라이언트가 핵심기능을 가진 클래스를 직접 사용하면 부가기능을 사용할 수 없음 클라이언트는 인터페이스를 통해서만 핵심기능을 사용 부가기능은 같은 인터페이스를 구현하여 끼어들어야 함 즉, 클라이언트는 부가기능을 통해 핵심기능을 이용하게 됨 프록시 : 자신이 클라이언트가 사용하려고 하는 실제 대상인 것처럼 위장해서 클라이언..
6.2 고립된 단위 테스트 가장 좋은 테스트 방법 : 가능한 작은 단위로 쪼개서 테스트 테스트 실패 시 원인을 찾기가 쉽기 때문 불가능한 경우도 있음 : 다른 오브젝트와 환경에 의존하고 있는 경우 6.2.1 복잡한 의존관계 속의 테스트 UserService 매우 간단한 기능만 가지고 있음 그럼에도 불구하고 세 가지 타입의 의존 오브젝트가 필요 UserDao : DB 처리 MailSender : 메일 처리 PlatformTransactionManager : 트랜잭션 처리 UserServiceTest 본래의 목적 : UserService에 대한 테스트 세 가지 의존관계를 갖고 있으므로 테스트가 진행되는 동안 세 가지 오브젝트가 모두 정상이어야 한다. 실제로는 해당 오브젝트의 뒤에 존재하는 훨씬 더 많은 오브젝트와 환경, 서비스, 서버..
6.1 트랜잭션 코드의 분리 트랜잭션 경계설정 비즈니스 로직보다 코드가 더 길다. 6.1.1 메소드 분리 트랜잭션 적용 코드 구조 트랜잭션 시작 비즈니스 로직 트랜잭션 종료 코드의 특징 두 가지 종류의 코드가 구분되어 있음 트랜잭션 & 비즈니스 로직 두 코드 간 주고받는 정보가 없음 완벽히 독립적인 코드 비즈니스 로직을 메소드로 추출하여 독립 public class UserService { public void upgradeLvls() throws Exception { TransactionStatus status = this.transactionManager.getTransaction(new DefaultTransactionDefinition()); try { upgradeLvlsInternal(); this.transactionM..
6장. AOP 개요 스프링의 3대 기반 기술 : IoC/DI, 서비스 추상화, AOP AOP : 가장 이해하기 힘든 난해한 용어와 개념을 가진 기술 AOP에 대한 이해 등장배경 스프링에 도입한 이유 AOP의 장점 가장 인기있는 AOP 적용 대상 선언적 트랜잭션 목차 실화야?목차 6.1 트랜잭션 코드의 분리 6.1.1 메소드 분리 6.1.2 DI를 이용한 클래스의 분리 DI 적용을 이용한 트랜잭션 분리 UserService 인터페이스 도입 분리된 트랜잭션 기능 트랜잭션 적용을 위한 DI 설정 트랜잭션 분리에 따른 테스트 수정 6.2 고립된 단위 테스트 6.2.1 복잡한 의존관계 속의 테스트 6.2.2 테스트 대상 오브젝트 고립시키기 테스트를 위한 UserServiceImpl 고립 고립된 단위 테스트 활용 UserDao ..
5.5 정리 비즈니스 로직을 담은 UserService 클래스를 만들고, 트랜잭션을 적용하면서 스프링의 서비스 추상화에 대해 알아보았다. 비즈니스 로직을 담은 코드는 데이터 액세스 로직을 담은 코드 분리되어야 한다. DAO의 기술 변화에 서비스 계층의 코드가 영향을 받지 않도록 인터페이스 DI를 활용하여 결합도를 낮추어야 한다. DAO에는 트랜잭션이 필요하다. 트랜잭션의 시작과 종료 지점을 지정하는 것은 트랜잭션 경계설정이라고 한다. 스프링이 제공하는 트랜잭션 동기화 기법을 활용하면 편리하게 트랜잭션을 사용할 수 있다. 트랜잭션 API의 종류와 방법은 다양하므로, 트랜잭션이 변경되면 경계설정 코드도 함께 변경되어야 한다. 이는 단일 책임 원칙에 위배되며, DAO가 사용하는 특정 기술에 대해 강한 결합을 만들어낸다. ..
5.4 메일 서비스 추상화 요구사항 : 레벨이 업그레이드 되는 사용자에게 안내 메일 발송 기능 추가 5.4.1 JavaMail을 이용한 메일 발송 기능 사용자의 이메일 정보를 관리해야함 DB에 email 필드 추가 User 클래스에 email 프로퍼티 추가 UserDao의 UserMapper와 insert(), update()에 email 필드 처리 UserDaoTest 수정 JavaMail 메일 발송 upgradeLvl()에서 메일 발송 메소드를 호출 public class UserService { protected void upgradeLvl(User user) { user.upgradeLvl(); userDao.update(user); sendUpgradeEmial(user); } private void sendUpgrade..