※当サイトの記事には、広告・プロモーションが含まれます。

Spring Frameworkで複数のapplicationContext.xmlを利用する

f:id:ts0818:20210528165331j:plain

www.itmedia.co.jp

 スクウェア・エニックスは5月27日、YouTubeで配信した「ドラゴンクエスト35周年特番」で1988年に社会現象となった「ドラゴンクエストIII」をリメイクすると発表した。ドット絵をアレンジした新しいグラフィック手法を採用する。

「ドラクエ3」リメイク決定 順番を3→1→2にして「驚き」を - ITmedia NEWS

 ドラクエシリーズの生みの親である堀井雄二さんは、ドラクエ3のリメイクを決めた理由を「一番思い入れがあるから」と話す。さらに「続きが作れたらドラクエ1と2も。2で意外な展開を作りたい」という。

「ドラクエ3」リメイク決定 順番を3→1→2にして「驚き」を - ITmedia NEWS

⇧ おお~!

ドラゴンクエスト」生みの親は「ドラクエ3」推しなんですね~。

というわけで、今回はJavaフレームワークとして認知度の高いSpring Frameworkについてです。

レッツトライ~。 

 

Spring Framework と Spring Bootの違いって?

Githubリポジトリを見る限り、

github.com

⇧ プロジェクトが異なるっぽい。

docs.spring.io

1. What We Mean by "Spring"

The term "Spring" means different things in different contexts. It can be used to refer to the Spring Framework project itself, which is where it all started. Over time, other Spring projects have been built on top of the Spring Framework. Most often, when people say "Spring", they mean the entire family of projects. This reference documentation focuses on the foundation: the Spring Framework itself.

https://docs.spring.io/spring-framework/docs/5.3.8-SNAPSHOT/reference/html/overview.html#overview-spring

⇧ 出た出た...、ほんとに認識齟齬を発生させてくれるよね...。

まぁ、でも「Spring Framework」は全ての他の「Spring」のプロジェクトの大元って言ってるみたいなのと、

2.2 Framework Modules

The Spring Framework consists of features organized into about 20 modules. These modules are grouped into Core Container, Data Access/Integration, Web, AOP (Aspect Oriented Programming), Instrumentation, Messaging, and Test, as shown in the following diagram.

https://docs.spring.io/spring-framework/docs/4.3.x/spring-framework-reference/html/overview.html

⇧ ちょっと情報は旧いけど、「Spring Boot」は「Spring Framework」の「モジュール」から好きなものをチョイスしてる感じってことなんですかね。

ちなみに、上図のような「Spring Framework」の構成図みたいなものは、バージョンが「4.3.x」以降では「ドキュメント」から消えてるっぽいのよね...

ちなみに、2021年5月27日(木)現在、「ドキュメント」の最新バージョンは、

f:id:ts0818:20210526141921p:plain

f:id:ts0818:20210526142014p:plain

⇧ 5.3.8ってことになるのかな?

 

applicationContext.xmlって?

公式の説明によると、

spring.pleiades.io

org.springframework.context.ApplicationContext インターフェースは Spring IoC コンテナーを表し、Bean のインスタンス化、構成、組み立てを担当します。コンテナーは、構成メタデータを読み取ることにより、どのオブジェクトをインスタンス化、構成、アセンブルするかに関する指示を取得します。構成メタデータは、XMLJava アノテーション、または Java コードで表されます。アプリケーションを構成するオブジェクトと、それらのオブジェクト間の豊富な相互依存関係を表現できます。

https://spring.pleiades.io/spring-framework/docs/current/reference/html/core.html#beans-basics

⇧ ってな感じで、「Spring IoC コンテナ」が機能するための「構成メタデータ」を実現するもの、それが「applicationContext.xml」ってことになるみたいね。

ただ、「構成メタデータ」を実現する方法については、

の3つがあるらしいのと、

blog.okazuki.jp

⇧ 上記サイト様によりますと、「Spring Boot」を使ってる場合は、「applicationContext.xml」を自分で読み込むようにしないといけないっぽいことをしてることから、「Spring Boot」の内部の仕組みは分からんのだけど、「XML(Extensible Markup Language)」以外で「構成メタデータ」を用意する必要があるってことなのかね?

脱線しましたが、「Spring IoC コンテナ」については、

次の図は、Spring の機能の概要を示しています。アプリケーションクラスは構成メタデータと組み合わされ、ApplicationContext が作成および初期化された後、完全に構成された実行可能なシステムまたはアプリケーションができます。

f:id:ts0818:20210526133037p:plain

https://spring.pleiades.io/spring-framework/docs/current/reference/html/core.html#beans-basics

⇧ 上図のような感じで、「Spring」を利用したアプリケーションを動かすためには必須というか、「Spring IoC コンテナ」は「構成メタデータ」の情報があって初めて機能できるっぽいので、「構成メタデータ」めっちゃ重要、ってことなのかね?

で「Spring Framework」のドキュメントによると、

ほとんどのアプリケーションシナリオでは、Spring IoC コンテナーの 1 つ以上のインスタンスインスタンス化するために明示的なユーザーコードは必要ありません。例: Web アプリケーションのシナリオでは、通常、アプリケーションの web.xml ファイル内のボイラープレート Web 記述子 XML の単純な 8 行(またはそれ以上)で十分です(Web アプリケーション用の便利な ApplicationContext インスタンス化を参照)。

https://spring.pleiades.io/spring-framework/docs/current/reference/html/core.html#beans-basics

⇧ 上記の「Web アプリケーション用の便利なApplicationContextインスタンス化を参照」ってなってるので確認してみる。

1.15.5. Web アプリケーション用の便利な ApplicationContext インスタンス

ApplicationContext インスタンスを宣言的に作成するには、たとえば ContextLoader を使用します。もちろん、ApplicationContext 実装の 1 つを使用して、ApplicationContext インスタンスをプログラムで作成することもできます。

https://spring.pleiades.io/spring-framework/docs/current/reference/html/core.html#context-create

次の例に示すように、ContextLoaderListener を使用して ApplicationContext を登録できます。

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

リスナーは contextConfigLocation パラメーターをインスペクションします。

https://spring.pleiades.io/spring-framework/docs/current/reference/html/core.html#context-create

パラメーターが存在しない場合、リスナーは /WEB-INF/applicationContext.xml をデフォルトとして使用します。パラメーターが存在する場合、リスナーは事前定義の区切り文字(コンマ、セミコロン、空白)を使用して String を分離し、値をアプリケーションコンテキストが検索される場所として使用します。Ant スタイルのパスパターンもサポートされています。例は、/WEB-INF/*Context.xml (名前が Context.xml で終わり、WEB-INF ディレクトリにあるすべてのファイル用)および /WEB-INF/**/*Context.xml (WEB-INF のサブディレクトリ内のすべてのそのようなファイル用)です。

https://spring.pleiades.io/spring-framework/docs/current/reference/html/core.html#context-create

⇧ ってな感じで、デフォルトだと、「/WEB-INF/applicationContext.xml」が使用されるらしい。ちなみに、Eclipseで「Gradleプロジェクト」の依存関係で「Spring Boot」を追加しても、「WEB-INF」ディレクトリは空っぽだったので、「Spring Boot」は異なる仕組みで「構成メタデータ」が用意されてるっぽい気がする、たぶん...。

 

『リスナーは /WEB-INF/applicationContext.xml をデフォルトとして使用します。』の説明の件は何だったのか...

そして、悲報...

qiita.com

Spring Bootではプロジェクトのひな型を作成するツールがあるので簡単にプロジェクトを作成することができますが、Spring Frameworkの場合、そのようなツールがないので開発者が1から作成していく必要があります

Spring Web MVCを利用するプロジェクトのひな型を作成する手順 - Qiita

⇧ 上記サイト様によりますと、「Spring Framework」の雛型は自力で作らないといけないという...

どうりで、公式の「Spring Framework」のドキュメントで、

5. Getting Started

If you are just getting started with Spring, you may want to begin using the Spring Framework by creating a Spring Boot-based application. Spring Boot provides a quick (and opinionated) way to create a production-ready Spring-based application. It is based on the Spring Framework, favors convention over configuration, and is designed to get you up and running as quickly as possible.

https://docs.spring.io/spring-framework/docs/5.3.7/reference/html/overview.html#overview-getting-started

You can use start.spring.io to generate a basic project or follow one of the "Getting Started" guides, such as Getting Started Building a RESTful Web Service. As well as being easier to digest, these guides are very task focused, and most of them are based on Spring Boot. They also cover other projects from the Spring portfolio that you might want to consider when solving a particular problem.

https://docs.spring.io/spring-framework/docs/5.3.7/reference/html/overview.html#overview-getting-started

⇧「Spring Boot」を使う方法しか記載してないわけだ...

っていうか、「Spring Framework」のドキュメントなんだから、「Spring Boot」を使わない場合のケースについても掲載するべきでしょ...

公式のドキュメントが適当過ぎるんだよな~...

そもそもとして、公式のドキュメントに記載のあった『リスナーは /WEB-INF/applicationContext.xml をデフォルトとして使用します。』って説明の件は一体何だったんだ、ってなるよね...

www.atmarkit.co.jp

 クラスが作成できたら、以下のapplicationContext.xmlというファイルを作成します。このapplicationContext.xmlはアプリケーションのクラスパス上に配置してください。

DI:依存性の注入とは何か?:Spring Frameworkで理解するDI(1)(2/3 ページ) - @IT

⇧ う、う~ん...

皆さん、何を参考に「applicationContext.xml」の内容を決めてるんじゃろうか?

同じ様な疑問を抱えてらっしゃる方がおられました。

stackoverflow.com

With Spring 3 distribution there was a project folder which was packaged in the distribution . This project folder had sample applicationContext.xml file which can be used . However when I have downloaded Spring 4 distribution from here it does not come with a project folder and I am not able to find the sample applicationContext.xml. Where can I find the example applicationContext.xml file.

https://stackoverflow.com/questions/28414234/where-can-i-find-the-example-applicationcontext-xml-file

⇧ どうやら、「Spring 3系」までは公式で用意されてたらしいけど、「Spring 4系」からは無くなったらしい...

Oh, my gosh...

で、それに対するコメントしては、

BTW ,We dont need ApplicationConetxt in Spring 4 .Annotations are there to do all job.I face thi issue and then removed this file "ApplicationConetxt" and it worked. – Ankur Srivastava Feb 9 '17 at 21:41

https://stackoverflow.com/questions/28414234/where-can-i-find-the-example-applicationcontext-xml-file

Yes this is not new feature of Spring but it is hard to find a working applicationContext.xml in all blogs. – erhun Feb 11 '17 at 12:09

https://stackoverflow.com/questions/28414234/where-can-i-find-the-example-applicationcontext-xml-file

Also, many Spring projects are written using xml files like the applicationContext.xml so learning this legacy format is good when encountering these. – Mushy Sep 11 '17 at 15:35

https://stackoverflow.com/questions/28414234/where-can-i-find-the-example-applicationcontext-xml-file

⇧ どうやら「Spring 4系」からは、「applicationContext.xml」を使わない方針になったんですかね?

混乱するんで、公式のドキュメントに「applicationContext.xmlは使わないでください」とか一言あっても良い気がするんだけど...

もしくは、新しいドキュメントにも使用例を記載するようにするとかして欲しいかな...

 

実際に実装してみる

というわけで、

github.com

⇧ 上記サイト様にあるように、複数の「applicationContext.xml」を利用してみる。ただ、毎回異なる「applicationContext.xml」を使うってのは、Java側の実装でランダムで選ぶとかにすればよいのか、いまいち意図が見えんのよね...

このように機能要件・非機能要件が曖昧だと、実装で混乱することになるので、実務では必ず認識合わせが必須ですかね。

とりあえず、

fits.hatenablog.com

itsakura.com

⇧ 上記サイト様によりますと、「3系」と「5系」 で「applicationContext.xml」を読み込む方法自体は、変わらない模様。

Spring Framework 3系での「applicationContext.xml」読み込み

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");    

Spring Framework 5系での「applicationContext.xml」読み込み

ClassPathXmlApplicationContext context = 
				new ClassPathXmlApplicationContext("applicationContext.xml");

⇧ 受け取る変数は微妙に異なってるけど、どっちも「applicationContext.xml」自体の読み込みについては、

new ClassPathXmlApplicationContext("applicationContext.xml");

⇧ 上記の記述で共通してる模様。おそらく「4系」も同じ感じになるのかな?

かなり旧い情報になってしまうけども、

docs.spring.io

⇧ バージョン「3.0.0.M4」のドキュメントに読み込む方法は記載されておりました。

はい、脱線しましたが、「applicationContext.xml」を配置する場所は、「クラスパス」として認識されてる場所であれば良さ気ですと。

ただ、「ファイル名」だけでなく、「ファイルパス」を指定する場合については、 

code-examples-ja.hateblo.jp

ClassPathXmlApplicationContextを使って読み込みたい場合は、書き方に工夫がいる。

new ClassPathXmlApplicationContext("file:src/main/resources/beans.xml");

のように、file:を接頭辞につけなければいけない。

Spring Framework4のClassPathXmlApplicationContextで存在するはずのサービス定義ファイルが読み込めない場合の解決策 - Code Log

⇧ ってな感じで「file:」ってのを付けないといけないらしいとか、ハマりどころ満載ですね...。

www.shookuro.com

qiita.com

文字コードの設定については、

  • XML(Extensible Markup Language)で設定
  • Javaのコーディングで設定

のどっちかで大丈夫そう。 他にも設定方法がありそうな気がしてならないが...

「国際化(「i18n」)」に関わってきそうな「ロケール」なんかについては、 

qiita.com

⇧ 上記サイト様が詳しいです。

 

Eclipseで「Gradleプロジェクト」の場合の例になりますが、「.classpath」ファイルを確認すれば、「クラスパス」として認識されてる場所が確認できるっぽい。

f:id:ts0818:20210527140938p:plain

というわけで、「.classpath」ファイルを確認。 

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
	<classpathentry kind="src" output="bin/main" path="src/main/java">
		<attributes>
			<attribute name="gradle_scope" value="main"/>
			<attribute name="gradle_used_by_scope" value="main,test"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="src" output="bin/main" path="src/main/resources">
		<attributes>
			<attribute name="gradle_scope" value="main"/>
			<attribute name="gradle_used_by_scope" value="main,test"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="src" output="bin/test" path="src/test/java">
		<attributes>
			<attribute name="gradle_scope" value="test"/>
			<attribute name="gradle_used_by_scope" value="test"/>
			<attribute name="test" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="src" output="bin/test" path="src/test/resources">
		<attributes>
			<attribute name="gradle_scope" value="test"/>
			<attribute name="gradle_used_by_scope" value="test"/>
			<attribute name="test" value="true"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11/"/>
	<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
	<classpathentry kind="output" path="bin/default"/>
</classpath>    

⇧ ってな感じで、「Gradleプロジェクト」のデフォルトの状態では、

  • src/main/java
  • src/main/resources
  • src/test/java
  • src/test/resources
  • bin/default

の5つのディレクトリが「クラスパス」として有効らしい。

なので、実業務で使える使えないは置いておくとして、「src/main/resources」配下に、適当な「ディレクトリ」を作成して、「applicationContext.xml」を配置してあげれば良さそうですと。

というわけで、ディレクトリ構成とかは以下になりました。

f:id:ts0818:20210528145849p:plain

⇧ なんか、「applicationContext.xml」の無駄使い感が半端ないんだが、『複数のapplicationContext.xmlを用意し、毎回異なるapplicationContext.xmlを使用すること』ってお題だから致し方ないのかな?

というわけで、各ファイルを編集。 

/*
 * This file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Java Library project to get you started.
 * For more details take a look at the Java Libraries chapter in the Gradle
 * User Manual available at https://docs.gradle.org/6.3/userguide/java_library_plugin.html
 */

plugins {
    // Apply the java-library plugin to add support for Java Library
    id 'java-library'
}

repositories {
    // Use jcenter for resolving dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
}

dependencies {
    // This dependency is exported to consumers, that is to say found on their compile classpath.
    api 'org.apache.commons:commons-math3:3.6.1'

    // This dependency is used internally, and not exposed to consumers on their own compile classpath.
    implementation 'com.google.guava:guava:28.2-jre'

	// https://mvnrepository.com/artifact/org.springframework/spring-core
	implementation group: 'org.springframework', name: 'spring-core', version: '5.3.7'

	// https://mvnrepository.com/artifact/org.springframework/spring-context
	implementation group: 'org.springframework', name: 'spring-context', version: '5.3.7'

	// https://mvnrepository.com/artifact/org.springframework/spring-beans
	implementation group: 'org.springframework', name: 'spring-beans', version: '5.3.7'

    // Use JUnit test framework
    testImplementation 'junit:junit:4.12'
}

⇧ ってな感じで、依存関係としては「spring-core」「spring-context」「spring-beans」の3つがあれば、今回実施したいことは実現できそう。

■/Spring_Framework/src/main/java/Spring_Framework/service/Greeting.java

package Spring_Framework.service;

import java.util.Locale;

public interface Greeting {

  public String getHello(Locale locale);

}    

■/Spring_Framework/src/main/java/Spring_Framework/service/GreetingImpl.java

package Spring_Framework.service;

import java.util.Locale;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Component;

@Component
public class GreetingImpl implements Greeting {

	@Autowired
	MessageSource message;

	@Override
	public String getHello(Locale locale) {
		// 
		return message.getMessage("msg", null, locale);
	}
}

■/Spring_Framework/src/main/java/Spring_Framework/Library.java

/*
 * This Java source file was generated by the Gradle 'init' task.
 */
package Spring_Framework;

import java.io.File;
import java.util.Locale;
import java.util.Random;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import Spring_Framework.service.GreetingImpl;

public class Library {

  public static void main(String[] args) {
    // 「src/main/resources/language」のサブディレクトリのパス一覧を配列に格納
    String filePath = "src/main/resources/language";
    File[] files = new File(filePath).listFiles();

    // 「src/main/resources/language」のサブディレクトリの数の範囲内で乱数生成
    Random rand = new Random();
    int randomNum = rand.nextInt(files.length);

    // 生成した乱数で、配列から対象のパスを取得
    String targetLanguage = files[randomNum].getName();
    String targetContextPath = files[randomNum].getPath();

    //対象のパスに配置された「applicationContext.xml」から アプリケーションコンテキストを取得
    ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("file:" + targetContextPath +  File.separator + "applicationContext.xml");
    // 取得したBeanのメソッドを実施
    String result = ctx.getBean(GreetingImpl.class).getHello(getTargetLocale(targetLanguage));
    // 実行結果を表示
    System.out.println("GreetingImpl#getHello(Locale locale): 【" + getTargetLocale(targetLanguage) + "】"+ result);
    // アプリケーションコンテキストを閉じる(Beanファクトリ内のBeanすべて破棄)
    ctx.close();

  }

  // 言語に合うロケールを作成する
  private static Locale getTargetLocale(String targetLamguage) {
    switch (targetLamguage) {
    case "chinese":
      return Locale.CHINESE;
    case "english":
      return Locale.ENGLISH;
    case "french":
      return Locale.FRENCH;
    case "japanese":
      return Locale.JAPANESE;
    case "russian":
      return new Locale("ru");
    case "spanish":
      return new Locale("es");
	default:
	  return Locale.getDefault();
	}
  }

  // Eclipseで「Gradleプロジェクト」作成時にデフォルトで生成されたメソッド(今回不要)
  public boolean someLibraryMethod() {
    return true;
  }
}

【中国語】対応

■/Spring_Framework/src/main/resources/language/chinese/applicationContext.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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

	<!-- <bean id="testSyain" class="com.example.test1.Syain"></bean> -->
	<context:component-scan
		base-package="Spring_Framework.service" />
	<bean id="messageSource"
		class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<property name="basenames">
			<list>
				<value>language/chinese/message_zh</value>
				<value>language/chinese/error_zh</value>
			</list>
		</property>
		<property name="defaultEncoding" value="UTF-8" />
		<property name="fileEncodings" value="UTF-8" />
	</bean>
</beans>

■/Spring_Framework/src/main/resources/language/chinese/message_zh.properties

msg=你好,世界!  

■/Spring_Framework/src/main/resources/language/chinese/error_zh.properties

error.msg=错误!   

【英語】対応

■/Spring_Framework/src/main/resources/language/english/applicationContext.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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

	<!-- <bean id="testSyain" class="com.example.test1.Syain"></bean> -->
	<context:component-scan
		base-package="Spring_Framework.service" />
	<bean id="messageSource"
		class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<property name="basenames">
			<list>
				<value>language/english/message_en</value>
				<value>language/english/error_en</value>
			</list>
		</property>
		<property name="defaultEncoding" value="UTF-8" />
		<property name="fileEncodings" value="UTF-8" />
	</bean>
</beans>

■/Spring_Framework/src/main/resources/language/english/message_en.properties

msg=Hello World!    

■/Spring_Framework/src/main/resources/language/english/error_en.properties

error.msg=error!    

【フランス語】対応

■/Spring_Framework/src/main/resources/language/french/applicationContext.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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

	<!-- <bean id="testSyain" class="com.example.test1.Syain"></bean> -->
	<context:component-scan
		base-package="Spring_Framework.service" />
	<bean id="messageSource"
		class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<property name="basenames">
			<list>
				<value>language/french/message_fr</value>
				<value>language/french/error_fr</value>
			</list>
		</property>
		<property name="defaultEncoding" value="UTF-8" />
		<property name="fileEncodings" value="UTF-8" />
	</bean>
</beans>

■/Spring_Framework/src/main/resources/language/french/message_fr.properties

msg=Bonjour le monde!   

■/Spring_Framework/src/main/resources/language/french/error_fr.properties

error.msg=erreur!   

【日本語】対応

■/Spring_Framework/src/main/resources/language/japanese/applicationContext.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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

	<!-- <bean id="testSyain" class="com.example.test1.Syain"></bean> -->
	<context:component-scan
		base-package="Spring_Framework.service" />
	<bean id="messageSource"
		class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<property name="basenames">
			<list>
				<value>language/japanese/message_ja</value>
				<value>language/japanese/error_ja</value>
			</list>
		</property>
		<property name="defaultEncoding" value="UTF-8" />
		<property name="fileEncodings" value="UTF-8" />
	</bean>
</beans>

■/Spring_Framework/src/main/resources/language/japanese/message_ja.properties

msg=こんにちは 世界!    

■/Spring_Framework/src/main/resources/language/japanese/error_ja.properties

error.msg=エラー!    

【ロシア語】対応

■/Spring_Framework/src/main/resources/language/russian/applicationContext.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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

	<!-- <bean id="testSyain" class="com.example.test1.Syain"></bean> -->
	<context:component-scan
		base-package="Spring_Framework.service" />
	<bean id="messageSource"
		class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<property name="basenames">
			<list>
				<value>language/russian/message_ru</value>
				<value>language/russian/error_ru</value>
			</list>
		</property>
		<property name="defaultEncoding" value="UTF-8" />
		<property name="fileEncodings" value="UTF-8" />
	</bean>
</beans>

■/Spring_Framework/src/main/resources/language/russian/message_ru.properties

msg=Привет мир!

■/Spring_Framework/src/main/resources/language/russian/error_ru.properties

error.msg=ошибка!  

スペイン語】対応

■/Spring_Framework/src/main/resources/language/spanish/applicationContext.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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

	<!-- <bean id="testSyain" class="com.example.test1.Syain"></bean> -->
	<context:component-scan
		base-package="Spring_Framework.service" />
	<bean id="messageSource"
		class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<property name="basenames">
			<list>
				<value>language/spanish/message_es</value>
				<value>language/spanish/error_es</value>
			</list>
		</property>
		<property name="defaultEncoding" value="UTF-8" />
		<property name="fileEncodings" value="UTF-8" />
	</bean>
</beans>

■/Spring_Framework/src/main/resources/language/spanish/message_es.properties

msg=Hola Mundo!   

■/Spring_Framework/src/main/resources/language/spanish/error_es.properties

error.msg=error!    

⇧ という感じで、国が増えるたびにファイルを増加しないといけないというイケて無さが、ゲスの極み!な構成になってしまいましたが、実行すると、

f:id:ts0818:20210528155222p:plain

乱数でランダムに選択された「applicationContext.xml」を読み込んだ結果が「コンソール」に表示されますと。

中国美人からの「こんにちは 世界!」

f:id:ts0818:20210528155854p:plain

アメリカ美人からの「こんにちは 世界!」

f:id:ts0818:20210528160126p:plain

日本美人からの「こんにちは 世界!」

f:id:ts0818:20210528155728p:plain

フランス美人からの「こんにちは 世界!」

f:id:ts0818:20210528160011p:plain

ロシア美人からの「こんにちは 世界!」

f:id:ts0818:20210528155252p:plain

スペイン美人からの「こんにちは 世界!」

f:id:ts0818:20210528155928p:plain

⇧ という感じで、世界の美女たち(ただの「コンソール」だとしても、豊かな想像力、否、妄想力を発揮すれば美女とかに見えて...こない...)からの「こんにちは 世界!」が見れたという事で、ミッションコンプリートですかね。

っていうか、何かもっと上手い「国際化(「i18n」)」の方法を教えて欲しい...

ちなみに、「文部科学省」が公開してる情報によりますと、

www.mext.go.jp

⇧ 使用してる母国語の人口別ランキングで、日本語が「10位」内に入ってるけど、人口減少が進むと「10位」圏外になりそうですかね...

ちなみにちなみに、「国の面積」については、

国の面積順リスト(くにのめんせきじゅんリスト)は、ISO標準のISO 3166-1によって分類された独立国家とその属領を、総面積順に並べた一覧である。資料により面積が異なるので、詳しくは各国家のページの面積を参照。

国の面積順リスト - Wikipedia

各国が領有権を主張する南極大陸(14,400,000 km2)はランキングに含めていない。また、無主地の一つであるビル・タウィール(2,060 km2)は関係国であるエジプトとスーダンには含めていない。世界の総陸地面積は、148,940,000 km2 で、地球上の表面積の約29.1% である。

国の面積順リスト - Wikipedia

⇧ とあり、

⇧ 日本は「62位」とあり、「世界の国の数」が「196か国」らしいので、

www.mofa.go.jp

世界の国の数: 196か国です。これは、現在、日本が承認している国の数である195か国に日本を加えた数です。最近では、ニウエ(2015年5月15日)、南スーダン(2011年7月9日)及びクック(2011年3月25日)を承認しました。

世界と日本のデータを見る(世界の国の数、国連加盟国数、日本の大使館数など)|外務省

⇧ 「62/196位」ということなので、意外にも世界的には上位の大きさと言えるんですかね?

まぁ、脱線しましたが、「Spring Framework」の情報も錯綜してるっぽいので、実際に動かしてみて情報の確かさを検証していく必要があるってことですかね...。

公式のドキュメントで情報が整理されてれば苦労はしないんですけどね...

今回はこのへんで。