ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring 기초예제 1-1
    Java/Spring 2020. 3. 5. 01:48

    예제를 통해 Spring의 사용법을 알아보겠습니다.

     

    다음과 같은 자바 코드가 존재한다고 가정해보겠습니다.

     

    샘플 코드 1

     

    HelloApp.java

    public class HelloApp {
        public static void main(String[] args) {
            MessageBean bean = new MessageBean();
            bean.sayHello("Spring");
        }
    }

     

     

    MessageBean.java

    public class MessageBean {
        public void sayHello(String name) {
            System.out.println("Hello, " + name + "!");
        }
    }

     

     

     

     

    위 코드를 실행하면 다음과 같은 결과를 출력합니다

     

    (혹시나 Ctrl+R 버튼이 먹히지 않는다면 HelloApp.java 파일을 우클릭 한 뒤, Run을 직접 눌러주세요)

     

     

     

    HelloApp 클래스는 사용할 MessageBean 클래스의 인스턴스를 직접 생성해서 sayHello() 메소드를 호출하게 되는데, 이 경우에 HelloApp 클래스가 MessageBean 클래스의 구현에 강하게 의존하게 됩니다.(강한 결합)

     

    클래스 간 결합이 강해지고, 의존하고 있는 클래스에 변경이 생기면, 코드를 수정해야 하는 범위가 넓어질 가능성이 높아집니다.

     

     

     

     

    샘플 코드 2 (인터페이스 적용)

     

    HelloApp.java

    public class HelloApp {
        public static void main(String[] args) {
            MessageBean bean = new MessageBeanKr();
            bean.sayHello("Spring");
        }
    }

     

    MessageBean.java

    public interface MessageBean {
        public void sayHello(String name);
    }

     

    MessageBeanEn.java

    public class MessageBeanEn implements MessageBean {
        public void sayHello(String name) {
            System.out.println("Hello, " + name + "!");
        }
    }

     

    MessageBeanKr.java

    public class MessageBeanKr implements MessageBean {
        public void sayHello(String name) {
            System.out.println("안녕하세요, " + name + "!");
        }
    }

     

     

     

    출력 결과

    Sample 2 Run

     

     

    2번 예제는 인터페이스를 상속함으로써 인터페이스와 구현 부분을 분리해서 코딩하고 있습니다. 따라서 인터페이스 변경이 없다면 구현 부분이 바뀌어도 이용하는 부분(HelloApp)이 받는 영향을 최소화할 수 있습니다.

     

    그러나 인터페이스를 사용하더라도 생성되는 인스턴스의 구체적인 클래스 이름은 기술해야 합니다. 위의 예에서는

    "new MessageBeanKr()" 부분을 MessageBeanEn 클래스로 변경하려면 "new MessageBeanEn()" 으로 코드를 바꿔 작성해야 합니다. 

     

    이 같은 문제를 해결하기 위한 "Factory Method" 디자인 패턴이 잘 알려져 있지만, 스프링으로 해결이 가능합니다. 다음에 설명할 샘플 코드 3은, 스프링을 사용해 이 문제를 해결하고 있습니다.

     

     

     

    샘플 코드 3 (스프링 적용)

     

    HelloApp.java

    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.xml.XmlBeanFactory;
    import org.springframework.core.io.FileSystemResource;
    
    public class HelloApp {
    
    	public static void main(String[] args) {
    
    		BeanFactory factory = new XmlBeanFactory(
            	new FileSystemResource("spring-config.xml"));
    		MessageBean bean = factory.getBean("messageBean", MessageBean.class);
    		bean.sayHello("Spring");
    	}
    }

     

    MessageBean.java

    public interface MessageBean {
        public void sayHello(String name);
    }

     

    MessageBeanEn.java

    public class MessageBeanEn implements MessageBean {
        public void sayHello(String name) {
            System.out.println("Hello, " + name + "!");
        }
    }

     

    MessageBeanKr.java

    public class MessageBeanKr implements MessageBean {
        public void sayHello(String name) {
        	System.out.println("안녕하세요, " + name + "!");
        }
    }

     

    spring-config.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="messageBean" class="MessageBeanEn" />
    </beans>

     

    프로젝트의 현재 파일 디렉토리 구조는 다음과 같습니다.

     

    Directory

     

    출력 결과

     

     

    샘플 코드 3의 핵심은 HelloApp이 사용하는 클래스(MessageBeanEn)의 클래스 이름을 코드에 직접 작성하지 않는다는 점입니다.

     

    앞부분 소스코드에서 getBean() 함수의 인수에 지정되어 있는  messageBean은 클래스 이름이 아닌, 단순한 문자열 식별자입니다.

     

    이 식별자에 대응하는 클래스는 외부 정의파일(스프링 설정파일 xml) 에 정의되어 있기 때문에, HelloApp 클래스에서 사용하는 클래스를 변경하는 경우 외부 정의 파일을 수정하기만 하면 됩니다. 즉, 프로그램 자체를 변경할 필요가 없어집니다.

     

     

     

    스프링을 사용해 Bean을 취득하는 경우 다음과 같은 절차를 따릅니다.

     

    • 1. Bean 팩토리를 생성한다.
    • 2. Bean 팩토리로부터 Bean을 취득한다.

     

    스프링 기능에서 Bean의 생성과 설정, 관리 등의 역할을 맡는 부분을 "Bean 팩토리" 라고 부릅니다.

    XML 정의 파일을 사용하는 경우, FileSystemResource 또는 ClassPathResource 클래스를 호출하여 사용합니다.

     

    FileSystemResource 클래스의 생성자에는 XML 정의 파일을 지정합니다.

     

    HelloApp.java

    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.xml.XmlBeanFactory;
    import org.springframework.core.io.FileSystemResource;
    
    public class HelloApp {
    
    	public static void main(String[] args) {
    
    		BeanFactory factory = new XmlBeanFactory(new FileSystemResource("spring-config.xml"));
    		MessageBean bean = factory.getBean("messageBean", MessageBean.class);
    		bean.sayHello("Spring");
    	}
    }

     

    위 코드에 의해 XML 정의 파일(spring-config.xml)의 정의 정보를 사용하는 BeanFactory 객체가 생성됩니다.

     

    BeanFactory 객체를 생성하고 나면, getBeans() 함수를 호출해서, 사용하려는 Bean 객체를 받아옵니다.

     

    getBeans()의 매개변수는 xml 파일에서 정의한 Bean 이름, 두 번째 매개변수는 BeanFactory에서 취득할 클래스를 지정합니다.

     

     

    XML 설정 파일

     

    위 예제 코드의 xml 정의 파일은 다음과 같습니다

     

    spring-config.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="messageBean" class="MessageBeanEn" />
    </beans>

     

    위 xml 파일은 BeanFactory 설정을 정의하는 파일이고, XmlBeanFactory 객체를 생성할 때 넘깁니다.

     

    bean 요소의 속성

    속성 의미 기본값
    id Bean에 붙이는 식별자(고유값) -
    name id에 대한 별칭, 복수정의 가능 -
    class Bean 클래스 이름, 완전한 형태의 클래스 이름으로 기술한다 -
    parent Bean 정의를 상속하는 경우 지정하는 새로운 Bean의 Id -
    abstract Bean 클래스가 추상 클래스인지 여부 false
    singleton Bean이 싱글톤으로 관리되는지 여부 true
    lazy-init Bean의 로딩을 지연시킬지 여부 default
    autowire 오토와이어 설정 default
    dependency-check 의존관계확인 방법 default
    depends-on 이 Bean이 의존할 Bean 이름. 먼저 초기화되는 것이 보장된다 -
    init-method Bean초기화시 실행시킬 함수 -
    destroy-method Bean 컨테이너 종료시 실행시킬 함수 -

    id, class, name 속성 사용법을 기억하면 좋습니다.

     

     

     

     

    위 xml의 경우 MessageBeanEn 클래스에 대해 "messageBean"이라는 이름을 쓰고 있습니다.

     

    id 속성으로 정의한 이름은 getBean() 함수의 인수에 지정할 이름이 됩니다.

     

    • MessageBean bean = factory.getBean("messageBean", MessageBean.class);

     

    name 속성을 사용하면 id 속성에서 지정한 이름의 별칭을 정의할 수 있습니다. (복수정의 가능)

    • <bean id="messageBean" name="a b c" class="MessageBeanEn" />
    • <bean id="messageBean" name="a,b,c" class="MessageBeanEn" />
    • <bean id="messageBean" name="a;b;c" class="MessageBeanEn" />
    • <bean id="messageBean" name="a;b,c" class="MessageBeanEn" />

    네 가지 모두 같은 결과.

     

    각각의 name을 스페이스 혹은 콤마, 세미콜론으로 구분합니다. 따라서 factory.getBean() 함수를 다음과 같이 사용할 수 있습니다.

    • MessageBean bean = factory.getBean("messageBean", MessageBean.class);
    • MessageBean bean = factory.getBean("a", MessageBean.class);
    • MessageBean bean = factory.getBean("b", MessageBean.class);
    • MessageBean bean = factory.getBean("c", MessageBean.class);

    따라서 마지막으로, 사용하는 Bean을 MessageBeanEn 클래스에서 MessageBeanKr 클래스로 변경하면 다음과 같습니다.

     

    spring-config.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="messageBean" class="MessageBeanKr" />
    </beans>

     

    출력 결과

    MessageBeanKr 출력 결과

     

     

    참고 서적 : 한빛미디어 / 예제로 쉽게 배우는 스프링 프레임워크 3.0 (사카타 코이치 지음, 황선유 옮김, 박성철 감수)

    'Java > Spring' 카테고리의 다른 글

    Spring 기초예제 1-2  (0) 2020.03.06
    Spring 초기 설정  (0) 2020.03.05
Designed by Tistory.