Old Branch

Spring Framework Documentation - IoC Container -2

woolbro 2019. 6. 18. 15:08
반응형

이전 포스팅입니다

[Java/Spring-framework] - Spring Framework Documentation -3 (IoC Container - 1)

 

Spring Framework Documentation -3 (IoC Container - 1)

이전포스팅입니다 :) [Java/Spring-framework] - Spring Framework Documentation -2 (Eclipse STS, IntelliJ) Spring Framework Documentation -2 (Eclipse STS, IntelliJ) 이전 포스팅입니다 [Java/Spring-frame..

woolbro.tistory.com

 

이전 포스팅의 내용을 요약하자면, IoC에 관한 내용과 클래스를 호출하는 방식에 대해서 얘기했는데요.

 

코드로 설명 드렸듯이, IoC를 적용하기 위한 준비. 즉 DI를 하기위한 준비에 대해서는 3가지가 있습니다.

 

스프링의 DI를 활용하기위해서는 DI를 사용할 객체를 프레임워크에 알려줘야 합니다. 위의 IoC/DI의 모식도에서 보여지는 ‘Configuration Metadata’의 설정과정인데요 이렇게 IoC Container에 등록되어지는 객체들을 ‘Bean’이라고 합니다.
먼저 Bean 을 등록하기 위한 방법으로는 3가지 방법이 있습니다.

 

  • XML-Based configuration
  • Annotation-based configuration
  • Java-based configuration

 

이번 포스팅에서는 Bean의 사용법, Bean의 범위와 BeanFactory와 ApplicationContext를 얘기 하겠습니다.

 

Bean의 사용법

이전포스팅에서는, Bean 사용 예제가 bean XML을 수정하고, Java단에서 이어주는 방법으로 사용 했었는데요, 이번 포스팅에서는 어노테이션을 활용한 방법을 보겠습니다.

 

다음은 Database 연결을 설정하는 Datasource config와, DAO입니다.

 

//Datasource Config

@Configuration
public class DatasourceConfig { 

    @Autowired
    ApplicationContext applicationContext;

    @Primary
    @Bean(name="dataSource")
    @ConfigurationProperties(prefix = "spring.datasource") 
    public DataSource dataSource() { 
        return DataSourceBuilder.create().build(); 
    } 

    @Primary
    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory() throws Exception { 
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); 
        sqlSessionFactoryBean.setDataSource(dataSource()); 
        sqlSessionFactoryBean.setMapperLocations
        		(applicationContext.getResources("classpath:mybatis/mapper/sql.xml")); 
   
        return sqlSessionFactoryBean.getObject(); 
    } 

    @Primary
    @Bean(name = "sqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate() throws Exception { 
        return new SqlSessionTemplate(sqlSessionFactory()); 
    } 
}
// DAO

public class Dao{

    @Autowired
    @Qualifier("sqlSessionTemplate")
    private SqlSessionTemplate sqlSession;
}

 

DB Connection을 관리하는 Datasource는 하나의 객체로서 연결풀을 관리하도록 합니다. 이를 위해 Spring 에서는 IoC 컨테이너에 'Singleton' 방식으로 IoC Container에 등록해 여러 DAO에 주입시켜 사용 할 수 있도록 합니다.

 

@Bean 과 @Autowired가 보이실텐데요, 두 어노테이션을 활용해 IoC 컨테이너에 등록하고, 의존성을 주입받아 사용 하는 것을 확인 하실 수 있습니다.

 

Bean Scope

Bean은 기본적으로 Singleton 의 형태로 관리됩니다. 하지만 Bean마다 Scope를 정의해서 관리 할 수 있습니다. 각각의 Bean의 사용 목적에 따라 달라집니다.

 

Scope 설명
singleton Spring IoC 컨테이너 내에서 단 하나의 객체만 존재한다
prototype Spring IoC Container 내에서 다수의 객체가 존재 가능하다
request HTTP Request life-cycle 내에 단 하나의 객체만 존재한다
session HTTP Session life-cycle 내에 단 하나의 객체만 존재한다
application ServletContextlife-cycle 내에 단 하나의 객체만 존재한다
web-socket session WebSocket life-cycle 내에 단 하나의 객체만 존재한다

싱글톤으로 사용하게되면 하나의 객체가 여러 참조 위치에서 사용되기때문에 변화가 생길경우 타 참조위치들에 변화를 동기화시키는데 비용이 들 수 있습니다. 때문에 사용 목적에 따라 싱글톤으로 사용할지 비싱글톤으로 사용할지 고려를 해야합니다.

 

일반적으로 "싱글톤" 객체는, 상태가 없는 객체, 데이터를 불러오는 용도로 사용하는 객체, 공유가 필요한 상태를 지닌 객체, 사용빈도가 높은 객체 의 특징을 가지고 있습니다.

 

Singleton

XML기반의 Bean scope를 정할때는 아래와 같이 정의할 수 있습니다.

 

<bean id="accountService" class="com.something.DefaultAccountService"/>

<!-- the following is equivalent, though redundant (singleton scope is the default) -->
<bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>

 

어노테이션 기반으로 정하려면 @Scope를 사용 해 줍니다.

@RequestScope, @SessionScope, @ApplicationScope이 있습니다.

 

@Component
@Scope(value="prototype")
public class Worker {}

/////////////////////////////
@Component
@Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class Worker {}

/////////////////////////////
/*
Request의 Bean 정의에 대해 XML구성은 아래와 같이
<bean id="loginAction" class="com.something.LoginAction" scope="request"/>
*/
@RequestScope
@Component
public class LoginAction {
    // ...
}

/////////////////////////////
/*
세션범위의 Bean 정의에 대해 XML구성은 아래와 같이
<bean id="userPreferences" class="com.something.UserPreferences" scope="session"/>
*/
@SessionScope
@Component
public class UserPreferences {
    // ...
}

/////////////////////////////
/*
application 범위의 Bean 정의에 대해 XML 구성은 아래와 같이
<bean id="appPreferences" class="com.something.AppPreferences" scope="application"/>
*/
@ApplicationScope
@Component
public class AppPreferences {
    // ...
}

 

BeanFactory 그리고 ApplicationContext

 

Feature BeanFactory ApplicationContext
Bean instantiation/wiring Y Y
Integrated lifecycle management N Y
Automatic BeanPostProcessor registration N Y
Automatic BeanFactoryPostProcessor registration N Y
Convenient MessageSource access (for internalization) N Y
Built-in ApplicationEvent publication mechanism N Y

우리가 여태까지 IoC Container라 지칭했던 컨테이너는 Spring Container라고도 이야기 하며 빈팩토리 혹은 애플리케이션 컨텍스트 라고도 불립니다. 정확하게 말하자면, IoC Container에는 2가지 종류가 있습니다. 위에서 이야기한 빈팩토리와 애플리케이션 컨텍스트 입니다. 사실 애플리케이션 컨텍스트는 빈팩토리 인터페이스를 상속시켜 확장한 클래스로, 빈팩토리의 모든 기능을 지원합니다.

 

BeanPostProcessor와 BeanFactoryPostProcessor 은 빈 등록후 변경 및 후처리를 진행할때 사용되는 클래스로, ApplicationContext의 경우 자동으로 해당 클래스를 감지하여 처리 해 줄수 있습니다.

 

ApplicationContext는 Beanfactory의 모든 기능들을 포함하고, AOP 서비스, 편리한 메시지 소스 접근, 내장 애플리케이션 이벤트 처리 메커니즘 등의 이유들을 바탕으로 공식문서에서는 Beanfactory 보다는 ApplicationContext사용을 권장하고 있습니다.