본문 바로가기

스프링

[spring] aop_팩토리빈_4

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

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

3.     Com.springsource.junit : junit

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

5.     Mail : java-mail

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

7.     Mysql-connector : Mysql JDBC

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

9.     Spring-aop : 스프링 기능 자체의 aop

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

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

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

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

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

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

16.   Spring-test.jar

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

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

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

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

 

 

사실 스프링은 클래스 정보를 가지고 디폴트 생성자를 통해 오브젝트를 만드는 방법 외에도 빈을 만들 수 있는 여러가지 방법을 제공한다.

팩토리빈 : 스프링을 대신해서 오브젝트의 생성로직을 담당하도록 만들어진 특별한 빈.

> 팩토리빈을 만드는 방법에는 여러가지가 있는데, 가장 간단한 방법은 스프링의 FactoryBean이라는 인터페이스를 구현하는 것이다.

 

Message 클래스는 생성자가 private으로 선언되어 있어 생성자를 통해 오브젝트를 만들 수 없고, 대신 스태틱 팩토리 메소드 제공.

따라서 직접 빈으로 등록해서 사용할 수 없다.

사실 스프링은 private 생성자를 가진 클래스도 빈으로 등록해주면 리플렉션을 이용해 오브젝트를 만들기에, 리플렉션은 private으로 선언된 접근 규약을 위반할 수 있는 강력한 기능이 있다. 하지만 스태틱 메소드를 통해 오브젝트가 만들어져야하는 중요한 이유가 있기 때문에 무시하고 강제로 생성하는 것은 위험하다.

 

 

5. FactoryBean<Message> : 생성할 오브젝트 타입을 Message로 지정해줘도 되지만, 범용적으로 사용하려면 Object로 사용해도 됨.

5. 스프링은 FactoryBean 인터페이스를 구현한 클래스가 빈의 클래스로 지정되면

13. getObject() 메소드를 이용해 오브젝트를 가져오고, 이를 빈 오브젝트로 사용한다.

21. getObjectType : Message 빈의 타입은 getObjectType의 리턴타입으로 결정됨.

30. return false : 싱글톤 빈이 아닌 getObject()가 매번 같은 오브젝트를 리턴하지 않는다는 의미.

 

 

빈의 아이디와 클래스를 지정하는 부분에는 차이가 없다.

하지만, 여타 빈 설정과 다른 점은 message 빈 오브젝트 타입이 class 애트리뷰트에 정의된 MessageFactoryBean이 아닌 Message 타입이라는 것이다.

Message 빈의 타입은 MessageFactoryBeangetObjectType() 메소드가 돌려주는 타입으로 결정된다.

>  또, getObject() 메소드가 생성해주는 오브젝트가 message 빈의 오브젝트가 된다.

 

 

 

20. @Autowired 타입의 자동와이이링 대신 ApplicationContext를 이용해 getBean() 메소드를 사용해봤다. getBean()Object 타입으로 리턴한다.

27. 드물지만 팩토리 빈이 만들어주는 빈 오브젝트가 아닌 팩토리 빈 자체를 가져오고 싶을 때는 ‘&’를 빈 이름 앞에 붙여주면 팩토리 빈 자체를 돌려준다.

 

 

레벨의 다음레벨 셋팅은 레벨에게 위임

 

User 객체에 레벨값 세팅은 User에게 위임 Service의 분기처리가 줄어듬

 

 

스프링에서 구현한 JDBCTemplate 활용한 JDBC DAO 전략

 

 

 

* 스프링은 설정파일(ex: applicationContext.xml)의 종류만큼 어플리케이션 컨텍스트를 만들고, @ContextConfiguration을 통해 위치지정.

20. 팩토리빈은 다이내믹 프록시가 위임할 타깃 오브젝트

23. serviceInterface : 리턴타입이 Class 타입은 value를 이용해 클래스 또는 인터페이스의 이름을 넣어주면 해당 Class 오브젝트로 자동 변환해준다.

* 단점 : 인터페이스 타겟 변환시 FactoryBean이 끊없이 늘어난다.

 

 

 

메일 테스트 스텁

 

 

프록시와 타깃을 위한 인터페이스

 

 

타깃 구현체(비즈니스 로직) 트랜잭션 코드가 들어와도 변해서는 안되는 로직

 

 

JDK 다이내믹 프록시 부가기능 구현

 

 

8. 다이내믹 프록시와 같이 스프링빈으로 등록하기 어려운 객체의 경우 FactoryBean을 구현한다. FactoryBean을 통해<생성할 오브젝트 타입명시>

29. getObject() 메소드에서 다이내믹 프록시 오브젝트를 만들어주면 되기 때문

40. getObjectType : FactoryBean 스프링 빈 설정시 리턴타입 명시. 팩토리 빈이 생성하는 오브젝트 타입. 다양한 타입의 프록시 오브젝트 생성에 재사용 가능. , 다른 서비스 인터페이스로 프록시 오브젝트로 리턴이 가능하다.

 

스프링 팩토리빈

타깃과 메소드 선정 알고리즘은 DI를 통해 분리가 가능하지만, 한번 빈으로 구성된 특정 타깃을 위한 프록시에 제한된다..

단점

>  타깃마다 부가기능을 만들어야한다. 왜냐 타깃을 set시키기 때문에 부가기능에서

 

 

 

 

38. 팩토리 빈을 가져오려면 어플리케이션 컨텍스트가 필요하다.

UpgradeLevels : 목 오브젝트를 이용한 단위테스트

 

mockDao : 디비연동없이 서비스만을 테스트하기 위한 목오브젝트

105. add@autowired로 가져온 ServiceImpl을 사용하기에 트랜잭션과는 무관하고, UserService를 주입받는다 하더라도 TxProxyFactoryBean 팩토리 빈이 생성하는 다이내믹 프록시를 통해 UserService의 기능을 사용하게된다. 하지만 add()의 경우 트랜잭션이 적용되지 않은 메소드 이므로 다이내믹 프록시를 거쳐도 단순 위임 방식으로만 동작한다.

 

 

트랜잭션 기능을 확인하기 위해 TestUserService 사용해야한다. 하지만 트랜잭션 프록시 오브젝트의 타깃을 바꿔주려면?

테스트용 설정을 따로 만들거나 프록시 팩토리 빈 코드를 확장하는 방법

TxProxyFactoryBean을 직접 가져와 프록시 생성(124라인 &userService)

위와같이 TxProxyFactoryBean 코드의 수정 없이도 다양한 클래스에 적용할 수 있다.

Application.context의 주입만으로 프록시빈 오브젝트 생성가능. 트랜잭션 테스트 때문에 바꾼거지 원래는 걍 써도됨!!!

126. getObject() : 다이내믹 프록시 오브젝트를 만들어줌

 

 

 

 

예를 들어 coreService에 트랜잭션을 적용하는 로직이 필요하다면 위처럼 설정해주면 CoreServiceImpl의 모든 메소드에 트랜잭션 기능이 적용된다.

장점

DI설정 만으로 다양한 타깃 오브젝트에 적용이 가능하다.

다이내믹 프록시 생성 코드도 제거할 수 있다.

단점

한번에 여러 개의 클래스에 공통적인 부가기능을 제공하는 것은 일일이 빈설정의 중복이 발생한다.

트랜잭션 부가기능이 아닌 보안 기능을 제공하는 프록시를 추가하려면? 적용 대상 서비스 클래스가 200개 이면 XML 설정이 4,000라인으로 늘어날 수 있다.

 

 

프록시 팩토리빈 기법을 사용할 수 있다.