스프링의 애플리케이션 컨텍스트

2022. 1. 9. 21:42북리뷰/토비의 봄

728x90

오브젝트 팩토리를 이용한 스프링 IOC

기존에 제작한 DaoFactory를 스프링에서 사용이 가능하도록 변신시켜보자. 스프링에서는 스프링이 제어권을 가지고 직접 만들고 관계를 부여하는 오브젝트를 빈(Bean) 이라고 한다. 자바 빈 또는 엔터브라이즈 자바빈(EJB)에서 말하는 빈과 비슷한 오브젝트 단위의 예플리케이션 컴포넌트를 말한다. 동시에 스피링 빈은 스프링 컨테이너가 생성과 관계설정, 사용 등을 제어해주는 제어의 역전이 적용된 오브젝트를 가리키는 말이다.

스프링에서는 빈의 생성과 관계설정 같은 제어를 담당하는 IoC 오브젝트를 빈 팩토리(bean Factory) 혹은 애플리케이션 컨텍스트(application context)라고 부른다. 애플리케이션 컨텍스트는 별도의 정보를 참고해서 빈의 생성, 관계설정 등의 제어 작업을 총괄한다.

애플리케이션 컨텍스트 Configuration

일단 스프링을 사용하기 위해 gradle의 dependency를 추가하자

plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'

    implementation 'mysql:mysql-connector-java:8.0.27'
    implementation 'cglib:cglib:3.3.0'
    implementation 'commons-logging:commons-logging:1.2'
    implementation 'org.springframework:spring-context:3.0.7.RELEASE'
}

test {
    useJUnitPlatform()
}

스프링의 애플리케이션 컨텍스트가 사용할 수 있는 본격적인 설정정보로 만들어보자.

먼저 스프링이 빈 팩토리를 위한 오브젝트 설정을 담당하는 클래스라고 인식할 수 있도록 @Configuration이라는 애너테이션을 추가한다. 그리고 오브젝트를 만들어주는 메서드에는 @Bean이라는 애너테이션을 붙여준다.

package springbook.user.dao;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springbook.util.ConnectionMaker;
import springbook.util.impl.DConnectionMaker;

@Configuration
public class Config {
    @Bean
    public UserDao userDao() {
        return new UserDao(connectionMaker());
    }

    @Bean
    public ConnectionMaker connectionMaker() {
        return new DConnectionMaker();
    }
}

이전 포스트의 DaoFactory와 형태가 비슷하지 않은가? 사실 에너테이션을 제외하고 DaoFactory와 동일하다. 즉 @Configuration도 DaoFactory와 마찬가지로 객체를 생성하고 객체간 관계를 설정하는 역할을 한다

package springbook.user.dao;

import springbook.util.ConnectionMaker;
import springbook.util.impl.DConnectionMaker;

public class DaoFactory {
    public UserDao userDao() {
        return new UserDao(connectionMaker());
    }

    public ConnectionMaker connectionMaker() {
        return new DConnectionMaker();
    }
}

애플리케이션 컨텍스트 실행

이제 위에 제작한 Config를 바탕으로 애플리케이션 컨텍스트를 만들어보자.

package springbook.user.dao;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import springbook.user.domain.User;
import springbook.util.ConnectionMaker;
import springbook.util.impl.DConnectionMaker;

import java.sql.SQLException;

public class UserDaoTest {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        ApplicationContext context =
                new AnnotationConfigApplicationContext(DaoFactory.class);
        UserDao dao = context.getBean("userDao", UserDao.class);

        User user = new User();
        user.setId("whw ip");
        user.setName("test");
        user.setPassword("1234");

        dao.add(user);

        System.out.println(user.getId() + "등록성공");

        User user2 = dao.get(user.getId());
        System.out.println(user2.getName());
        System.out.println(user2.getPassword());

        System.out.println(user2.getId() + "조회성공");
    }
}

@Configuration이 붙은 자바코드를 설정정보로 사용하려면 AnnotationConfigApplicationContext를 이용하면 된다.
그러고 나서 getBean()를 이용해 UserDao의 오브젝트를 가져올 수 있다.
getBean()은 ApplicationContext가 관리한느 오브젝트를 요청하는 메서드다. getBean()의 파라미터인 "userDao"는 ApplicationContext에 등록된 빈의 이름이다. DaoFactory에서 @Bean이라는 애너테이션을 userDao라는 이름의 메서드를 붙였는데, 이 메서드 이름이 바로 빈의 이름이 된다.만약

  public UserDao asdfuserDao() {
        return new UserDao(connectionMaker());
    }

이런 식으로 지었다면

  UserDao dao = context.getBean("adsfuserDao", UserDao.class);

이런 식으로 가져올 수 있다.

애플리케이션 컨텍스트의 동작방식

위 내용만 보면, 기존에 DaoFactory만 사용하면 되지 굳이 왜 스프링을 써야하나 싶다. 허나, 스프링은 DaoFactory에서 얻을 수 없는 방대한 기능과 활용 방법을 제공해준다
DaoFactory가 UserDao를 비롯한 DAO 오브젝트를 생성하고 DB생성 오브젝트와 관계를 맺어주는 제한적인 역할을 하는 데 반해, 애플리케이션 컨텍스트는 애플리케이션에서 IOC를 적용해서 관리할 모든 오브젝트에 대한 생성과 관계설정을 담당한다.
대신 ApplicationContext에는 DaoFactory와 달리 직접 오브젝트를생성하고 관계를 맺어주는 코드가 없고, 그런 생성정보와 연관관계 정보를 별도의 설정정보를 통해 얻는다. 떄로는 외부의 오브젝트 팩토리에 그 작업을 위임하고 그 결과를 가져다가 사용한다.

애플리케이션 컨텍스트는 Config클래스를 설정정보로 등록해두고 @Bean이 붙은 메서드의 이름을 가져와 빈 목록을 만들어둔다. 클라이언트가 애플리케이션 컨텍스트의 getBean() 메서드를 호출하면 자신의 빈 목록에서 요청한 이름이 있는지 찾고, 있다면 빈을 생성하는 메서드를 호출해서 오브젝트를 생성시킨 후 클라이언트에 돌려준다.

DaoFactory를 오브젝트 팩토리로 직접 사용했을 때와 비교해서 애플리케이션 컨텍스트를 사용했을 때 얻을 수 있는 장점은 다음과 같다.

  1. 클라이언트는 구체적인 팩토리 클래스를 알 필요가 없다.
    ioc를 적용한 오브젝트도 계속 추가가 될 것인데, 그럴 때마다 어떤 팩토리 클래스를 사용하는지 알아야 하고 필요할때마다 생성해야하는 번거로움이 있다. 어플리케이션 컨텍스트를 사용하면 위 같은 경우 없이 일관된 방식으로 원하는 오브젝트를 가져올 수 있다.
  2. 애플리케이션 컨텍스트는 종합 ioc서비스를 제공해준다.
    오브젝트 생성방식, 시점, 전략을 변경할 수 있고, 자동생성, 후처리, 정보 조합, 설정방식 다변화, 인터셉팅 등 다양한 기능을 제공한다.
  3. 애플리케이션 컨텍스트는 빈을 검색하는 다양한 방법을 제공한다.
    빈 이름을 통한 검색 뿐만 아니라, 타입만으로 검색하거나, 특별한 에너테이션 설정이 있는 빈도 찾을 수 있다.
728x90