본문 바로가기

스프링

[spring] aop_프록시팩토리빈_포인트컷_코드트랜잭션_5

1.     Com.springsource.javax.activation : Spring java-mail

2.     Com.springsource.javax.mail : Spring java-mail

3.     Com.springsource.org.aopalliance : Spring ProxyFactoryBean

4.     Com.springsource.junit : junit

5.     Commons-logging : Spring-context가 사용

6.     Mail : java-mail

7.     Mockito : 목 프레임워크 중 Mockito

8.     Mysql-connector : Mysql JDBC

9.     Org.springframework.context.support : Spring java-mail

10.   Spring-aop : 스프링 기능 자체의 aop, Spring ProxyFactoryBean

11.   Spring-bean : 스프링 빈을 활용하는 경우 필요. 스프링의 XML 설정파일과 자바 애노테이션을 파싱 하는데 필요한 클래스 포함

12.   Spring-context : 스프링 코어를 확장한 많은 클래스가 들어 있는데 모든 클래스는 EJB, JNDI(Java Naming Directory Interface), JMX용 클래스와 연동하는데 applicationcontext기능을 사용해야 하며 스프링 리모팅 클래스, 동적 스크립팅 언어(제이루비, 그루비등)와 연동하는 클래스, 빈 유효성검증(JSR-303) API, 스케줄링을 하는 클래스도 포함되어 있다.

13.   Spring-core : 모든 스프링 모듈에서 필요한 모듈. 다른 스프링 모듈에서 사용하는 공통 클래스가 포함됨.

14.   Spring-dao : EmpltyResultDataAccessException 등 사용을 위한 jar

15.   Spring-expression : 스프링 표현언어(SpEL) 지원 클래스 포함.

16.   Spring-jdbc : 스프링이 지원하는 jdbc.

17.   Spring-test.jar

-       @RunWith : Junit 프레임워크의 테스트 실행방법을 확장시 사용.

-       SpringJUnit4ClassRunner : 어플리케이션컨텍스트를 만들고 관리하는 확장 클래스

-       @ContextConfiguration(경로) : 자동으로 만들어줄 어플리케이션 컨텍스트 설정파일

18.   Spring-tx : DuplicateKeyException.class 파일 존재 및 스프링 트랜잭션

 

JDK 다이내믹 프록시의 부가기능을 담기위한 InvocationHandler 구현체

 

 

16~25. JDK 다이내믹 프록시 생성

28. ProxyFactoryBean

> 스프링은 프록시를 생성해서 빈 오브젝트로 등록해주는 역할. 부가기능은 별도의 빈에 둠.

> 인터페이스 자동검출 기능으로 타깃 오브젝트가 구현하고 있는 인터페이스 정보를 알아내어 프록시를 생성해줌.

> setInterface() 메소드를 통해 구현해야할 인터페이스 지정 가능.

37. MethodInterceptor(메소드 실행을 가로채는 방식) : Advice의 서브인터페이스

> 프록시에서 사용할 부가기능은 해당 인터페이스를 구현해 만든다.

> invoke() 메소드는 ProxyFactoryBean으로부터 타깃 오브젝트에 대한 정보까지도 함께 제공받는다. 이 차이로 인해 MethodInterceptor는 타깃 오브젝트에 관계없이 독립적으로 만들어질 수 있다. 따라서, 타깃이 다른 여러 프록시에서 함께 사용할 수 있고, 싱글톤 빈으로 등록이 가능하다.

38. MethodInvocation : 일종의 콜백 오브젝트로 proceed() 메소드를 실행하면 타깃 오브젝트의 메소드를 내부적으로 실행해주는 기능이 있다. , 일종의 공유 가능한 템플릿처럼 작동하는 것이다.(아래 스샷 참조 모든 DaoexcuteSql() 을 날리면 하나의 오브젝트를 공유하는 것과 같다. *스프링의 JdbcTemplate의 예가 적절함)

> ProxyFactoryBean은 작은 단위의 템플릿/콜백 구조를 응용해서 적용했기 때문에 템플릿 역할을 하는 MethodInvocation을 싱글톤으로 두고 공유할 수 있다.

 

 

1.     MethodInvocation = 14.workWithStatementStrategy(템플릿)

2.     MethodInterceptor = StatemenntStrategy(콜백 : 안에서 호출되는 것을 목적으로 만들어진 오브젝트(자바는 메서드를 던질 수 없으므로)) 즉 전략

 

프록시는 클라이언트로부터 요청받으면 > 포인트컷에게 부가기능을 부여할 메소드인지 확인 > 어드바이스 호출, JDKInvocationHandler와 달리 직접 타깃을 호출하지 않음(타깃을 몰라도됨) > 타깃을 호출하려면 proceed() 호출, 어드바이스는 템플릿이고, 내부적으로 Invocation (MethodInvocation) 콜백을 가지고 있는 구조임

 

 

39. MethodInterceptor(메소드 실행을 가로채는 방식)

> 프록시에서 사용할 부가기능은 해당 인터페이스를 구현해 만든다.

> invoke() 메소드는 ProxyFactoryBean으로부터 타깃 오브젝트에 대한 정보까지도 함께 제공받는다. 이 차이로 인해 MethodInterceptor는 타깃 오브젝트에 관계없이 독립적으로 만들어질 수 있다. 따라서, 타깃이 다른 여러 프록시에서 함께 사용할 수 있고, 싱글톤 빈으로 등록이 가능하다.

> JDK다이내믹 프록시의 InnvocationHandler와 달리 메소드 선정을 할 수 없다. 여러 프록시가 공유하기 때문에 메소드 선정패턴을 넣을 수 없다.

- 프록시마다 MethodInterceptor를 따로 등록해야할까??

 

 

 

 

기존의 JDK 다이내믹 프록시 방식은 InvocationHandler에 메소드선정알고리즘 + 부가기능 2가지가 같이 엮여 있었다. 하지만 스프링 ProxyFactoryBean2기능을 구분했고, 어드바이스와 포인트컷은 모두 프록시에 DI로 주입된다. 그리고 프록시에서 공유가 가능하도록 싱글톤으로 등록된다.(프록시로부터 어드바이스, 포인트컷 독립시키고 DI를 사용하게 한 것 역시 전략 패턴)

*  어드바이스에는 템플릿/콜백 패턴으로 구성. 부가기능 템플릿과 MethodInvocation 타입 콜백 Objectproceed() 를 호출하면 타깃이 호출된다.

 

62. 포인트컷을 직접 만들 수도 있지만 Pointcut 구현 클래스가 있으므로 이를 사용하면 편함.

65. 포인트컷이 없을 땐 addAdvice() 메소드를 호출해서 어드바이스만 등록. 같이 등록시 addAdvisor()

> ProxyFactoryBean에는 여러 개의 어드바이스와 포인트컷이 추가될 수 있으므로, 따로 등록시 어떤 어드바이스(부가기능)이 어떤 포인트컷(메소드 선정)을 적용할지 애매해지기 때문.

어드바이저 = 포인트컷+어드바이스

 

스프링 프록시 팩토리빈 트랜잭션. 다음레벨의 정보 레벨에게 위임(서비스 간소화 if 제거)

 

 

User의 레벨셋팅은 User에게 위임(서비스 간소화 if제거)

 

JDBC,Hibernate,JDO,JPA 등 전략을 구사하기 위한 DAO인터페이스

 

 

JDBC전략구현

 

메일을 정상적으로 작동된다고 봤을 때 불필요한 메일 전송제거 테스트스텁

 

 

프록시와 타깃을 위한 인터페이스(데코레이터패턴, 다이내믹 프록시)

 

타깃

 

 

어드바이스(부가기능 구현) MethodInterceptor라는 Advice 서브인터페이스 구현

15. MethodInvocation 타입의 콜백을 이용한 덕분에 리플렉션을 통한 타깃 메소드 호출 등의 번거로운 작업은 제거 가능. 예외역시 InvocationTargetException으로 포장돼서 오는 것이 아니기 때문에 그대로 잡아서 처리하면 된다.

* 코드에 의한 트랜잭션

> PlatformTransactionManager를 통한 코드에 의한 트랜잭션은 잘 알고 있어야한다. 실제로 사용하는 경우는 많이 없지만 트랜잭션 에러시 getTransaction() 메소드를 통하여 현재 진행 중인 트랜젹션을 돌려받아 새로 시작된것인지 기존 트랜잭션에 참여한 것인지에 대한 정보를 확인할 수 있다.

 

 

17. interceptorNames : 어드바이스와 어드바이저를 동시에 설정해 줄 수 있는 프로퍼티. 리스트에 어드바이스나 어드바이저 빈 아이디를 값으로 넣어주면 된다. 이름이 다른 이유는 어드바이스와 어드바이저를 혼합해서 설정할 수 있도록 하기 위함.

만약 포인트컷 적용이 필요없다면 바로 transactionAdvice라고 넣을 수 있음.

31. transactionAdvice(부가기능)은 이제 모든 프록시에서 공유가능

35. pointcut 설정. 생성자 및 프로퍼티 모드 DI가능.

> 포인트컷이 필요하면 이름 패턴 지정해서 ProxyFactoryBean에 등록해 주면 된다.

> 트랜잭션이 필요한 곳에 일관된 명명규칙으로 하나의 포인터컷으로 충분할 수 있다.

37. advisor 설정

* 장점

- 부가기능이 타깃 오브젝트마다 새로 만들어지는 문제 개선. 부가기능에 타깃을 set시키는 부분이 제거되고 ProxyFactoryBean에 타깃을 셋팅시키므로

* 단점

- target이 변경되면 계속 ProxyFactoryBean 설정을 복붙해줘야함(중복)

- target을 제외한 어드바이스(부가기능), 포인트컷의 설정이 동일하다(중복)

 

 

 

 

 

add메소드에도 포인트컷 적용으로 트랜잭션 제외

 

 

트랜잭션 테스트를 위한 TestService정의로 ProxyFactoryBean을 주입하여 프록시 오브젝트 생성

 

 

 

 

이렇게 ProxyFactoryBean을 이용해서 많은 수의 서비스 빈에게 트랜잭션 부가기능을 적용할 수 있다.

* 장점

- 부가기능이 타깃 오브젝트마다 새로 만들어지는 문제 개선. 부가기능에 타깃을 set시키는 부분이 제거되고 ProxyFactoryBean에 타깃을 셋팅시키므로

* 단점

- target이 변경되면 계속 ProxyFactoryBean 설정을 복붙해줘야함(중복)

- target을 제외한 어드바이스(부가기능), 포인트컷의 설정이 동일하다(중복)