1. 概要

Spring Frameworkコアは、簡単に言えば、Beanの管理に使用されるIoCコンテナーです。

Springには、BeanFactoryとApplicationContextの2つの基本的なタイプのコンテナーがあります。 前者は、ここで紹介されている基本的な機能を提供します。 後者は前者のスーパーセットであり、最も広く使用されています。

ApplicationContext は、 org.springframework.context パッケージのインターフェースであり、いくつかの実装があり、ClassPathXmlApplicationContextはその1つです。

この記事では、ClassPathXmlApplicationContextによって提供される便利な機能に焦点を当てます。

2. 基本的な使用法

2.1. コンテナの初期化とBeanの管理

ClassPathXmlApplicationContext は、クラスパスからXML構成をロードし、そのBeanを管理できます。

Studentクラスがあります。

public class Student {
    private int no;
    private String name;

    // standard constructors, getters and setters
}

StudentBeanをclasspathxmlapplicationcontext-example.xmlで構成し、クラスパスに追加します。

<beans ...>
    <bean id="student" class="com.baeldung.applicationcontext.Student">
        <property name="no" value="15"/>
        <property name="name" value="Tom"/>
    </bean>
</beans>

これで、 ClassPathXmlApplicationContext を使用してXML構成をロードし、StudentBeanを取得できます。

@Test
public void testBasicUsage() {
    ApplicationContext context 
      = new ClassPathXmlApplicationContext(
        "classpathxmlapplicationcontext-example.xml");
    
    Student student = (Student) context.getBean("student");
    assertThat(student.getNo(), equalTo(15));
    assertThat(student.getName(), equalTo("Tom"));

    Student sameStudent = context.getBean("student", Student.class);
    assertThat(sameStudent.getNo(), equalTo(15));
    assertThat(sameStudent.getName(), equalTo("Tom"));
}

2.2. 複数のXML構成

Springコンテナを初期化するためにいくつかのXML構成を使用したい場合があります。 その場合、 ApplicationContext を構築するときに、いくつかの構成場所を追加する必要があります。

ApplicationContext context 
  = new ClassPathXmlApplicationContext("ctx.xml", "ctx2.xml");

3. 追加機能

3.1. SpringIoCコンテナを正常にシャットダウンします

WebアプリケーションでSpringIoCコンテナーを使用する場合、SpringのWebベースの ApplicationContext 実装は、アプリケーションのシャットダウン時にコンテナーを正常にシャットダウンしますが、次のような非Web環境で使用する場合スタンドアロンのデスクトップアプリケーションの場合、Spring IoCコンテナが正常にシャットダウンされ、destroyメソッドを呼び出してリソースを解放するように、自分でシャットダウンフックをJVMに登録する必要があります。

destroy()メソッドをStudentクラスに追加しましょう。

public void destroy() {
    System.out.println("Student(no: " + no + ") is destroyed");
}

これで、このメソッドを studentBeanのdestroyメソッドとして構成できます。

<beans ...>
    <bean id="student" class="com.baeldung.applicationcontext.Student" 
      destroy-method="destroy">
        <property name="no" value="15"/>
        <property name="name" value="Tom"/>
    </bean>
</beans>

次に、シャットダウンフックを登録します。

@Test
public void testRegisterShutdownHook() {
    ConfigurableApplicationContext context 
      = new ClassPathXmlApplicationContext(
        "classpathxmlapplicationcontext-example.xml");
    context.registerShutdownHook();
}

テストメソッドを実行すると、 destroy()メソッドが呼び出されていることがわかります。

3.2. MessageSourceによる国際化

ApplicationContext インターフェースは、 MessageSource インターフェースを拡張するため、国際化機能を提供します。

ApplicationContext コンテナーは、初期化時に MessageSource Beanを自動的に検索し、BeanにはmessageSourceという名前を付ける必要があります。

MessageSourceでさまざまな言語を使用する例を次に示します。

まず、 dialog ディレクトリをクラスパスに追加し、2つのファイルdialog_en.propertiesdialog_zh_CN.propertiesを追加しましょう。

dialog_en.properties

hello=hello
you=you
thanks=thank {0}

dialog_zh_CN.properties

hello=\u4f60\u597d
you=\u4f60
thanks=\u8c22\u8c22{0}

classpathxmlapplicationcontext-internationalization.xmlmessageSourceBeanを構成します。

<beans ...>
    <bean id="messageSource"
      class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>dialog/dialog</value>
            </list>
        </property>
    </bean>
</beans>

次に、MessageSourceを使用してさまざまな言語のダイアログワードを取得しましょう。

@Test
public void testInternationalization() {
    MessageSource resources 
      = new ClassPathXmlApplicationContext(
        "classpathxmlapplicationcontext-internationalization.xml");

    String enHello = resources.getMessage(
      "hello", null, "Default", Locale.ENGLISH);
    String enYou = resources.getMessage(
      "you", null, Locale.ENGLISH);
    String enThanks = resources.getMessage(
      "thanks", new Object[] { enYou }, Locale.ENGLISH);
 
    assertThat(enHello, equalTo("hello"));
    assertThat(enThanks, equalTo("thank you"));

    String chHello = resources.getMessage(
      "hello", null, "Default", Locale.SIMPLIFIED_CHINESE);
    String chYou = resources.getMessage(
      "you", null, Locale.SIMPLIFIED_CHINESE);
    String chThanks = resources.getMessage(
      "thanks", new Object[] { chYou }, Locale.SIMPLIFIED_CHINESE);
 
    assertThat(chHello, equalTo("你好"));
    assertThat(chThanks, equalTo("谢谢你"));
}

4. ApplicationContextへの参照

管理対象のBean内でApplicationContextの参照を取得する必要がある場合があります。これを行うには、ApplicationContextAwareまたは@Autowiredを使用できます。 ApplicationContextAwareの使用がどのように機能するかを見てみましょう。

次の名前のCourseクラスがあります。

public class Course {

    private String name;

    // standard constructors, getters and setters
}

コンテナのBeanに従ってコースを組み立てるTeacherクラスがあります。

public class Teacher implements ApplicationContextAware {
    
    private ApplicationContext context;
    private List<Course> courses = new ArrayList<>();
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }

    @PostConstruct
    public void addCourse() {
        if (context.containsBean("math")) {
            Course math = context.getBean("math", Course.class);
            courses.add(math);
        }
        if (context.containsBean("physics")) {
            Course physics = context.getBean("physics", Course.class);
            courses.add(physics);
        }
    }

    // standard constructors, getters and setters
}

courseBeanとteacherBeanをclasspathxmlapplicationcontext-example.xmlで構成しましょう。

<beans ...>
    <bean id="math" class="com.baeldung.applicationcontext.Course">
        <property name="name" value="math"/>
    </bean>

    <bean name="teacher" class="com.baeldung.applicationcontext.Teacher"/>
</beans>

次に–コースプロパティの注入をテストします。

@Test
public void testApplicationContextAware() {
    ApplicationContext context 
       = new ClassPathXmlApplicationContext(
         "classpathxmlapplicationcontext-example.xml");
    Teacher teacher = context.getBean("teacher", Teacher.class);
    List<Course> courses = teacher.getCourses();
 
    assertThat(courses.size(), equalTo(1));
    assertThat(courses.get(0).getName(), equalTo("math"));
}

ApplicationContextAware インターフェイスを実装する以外に、@Autowiredアノテーションを使用しても同じ効果があります。

Teacherクラスを次のように変更してみましょう。

public class Teacher {

    @Autowired
    private ApplicationContext context;
    private List<Course> courses = new ArrayList<>();

    @PostConstruct
    public void addCourse() {
        if (context.containsBean("math")) {
            Course math = context.getBean("math", Course.class);
            courses.add(math);
        }
        if (context.containsBean("physics")) {
            Course physics = context.getBean("physics", Course.class);
            courses.add(physics);
        }
    }

    // standard constructors, getters and setters
}

次に、そのテストを実行すると、結果が同じであることがわかります。

5. 結論

ApplicationContext は、 BeanFactory と比較してよりエンタープライズ固有の機能を備えたSpringコンテナーであり、ClassPathXmlApplicationContextは最も一般的に使用される実装の1つです。

そのため、この記事では、 ClassPathXmlApplicationContext の基本的な使用法、シャットダウン登録機能、国際化機能、参照の取得など、いくつかの側面を紹介しました。

いつものように、この例の完全なソースコードは、GitHubから入手できます。