山崎屋の技術メモ

IT業界で働く中で、気になること、メモしておきたいことを書いていきます。

【Spring Framework】component-scanのいろいろ①

以前の記事でSpringのアノテーションコンフィグについて記載した。

yyama1556.hateblo.jp

そこで登場した[component-scan]について、もう少し掘り下げてメモしておく。

以下のタグ/属性について記載する。

・context:component-scanタグのuse-default-filters属性

・context:include-filterタグ

・context:exclude-filterタグ

なお、環境はWindows7、JDK1.8、Spring 4.2.3。

基本サンプル

Mainクラスのmainメソッドで、Springコンテキストに登録されているbean名の一覧を表示する。

フォルダ構成。
f:id:yyama1556:20160810173038p:plain

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">
	<context:component-scan base-package="org.yyama.hoge" />
</beans>

[org.yyama.hoge]パッケージ以下で@Componentなどのアノテーションが付与されたクラスをコンテナに登録するように設定している。

Mainクラス。

package org.yyama;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
	public static void main(String... args) {
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
		for (String string : ctx.getBeanDefinitionNames()) {
			if (string.indexOf("spring") == -1)
				System.out.println(string);
		}
		ctx.close();
	}
}

ApplicationContextのgetBeanDefinitionNames()メソッドを使用して、登録されているbean名の一覧を取得している。ただし"spring"という文字列を含むbeanはSpringがデフォルトで登録するbeanなので表示から除外している。

Fugaクラス。

package org.yyama.hoge;

import org.springframework.stereotype.Component;

@Component
public class Fuga {
}

クラスがSpringにどのように登録されるかを調査するため、@Componentアノテーションを付けてクラス宣言しているだけ。

Piyoクラス。

package org.yyama.hoge;

import org.springframework.stereotype.Service;

@Service
public class Piyo {
}

こちらのクラスは@Serviceアノテーションを付けている。

本題とは関係ないが、一応、pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>org.springframework.samples</groupId>
	<artifactId>Sample</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>
		<!-- Generic properties -->
		<java.version>1.8</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<!-- Spring -->
		<spring-framework.version>4.3.2.RELEASE</spring-framework.version>
	</properties>
	<dependencies>
		<!-- Spring and Transactions -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
	</dependencies>
</project>

実行してみると。

fuga
piyo

[org.yyama.hoge]パッケージ配下で@Componentアノテーションが付与されているFugaクラスと@Serviceアノテーションを付与しているPiyoクラスがSpringに登録されていることがわかる。出力の"fuga"は先頭のFが小文字となっているが、これはクラス名の先頭1文字を小文字にした文字列がデフォルトでbean名としてSpringに登録されるから("piyo"も同じ)。

[use-default-filters="false"]を使ってみる

applicationContext.xmlのcomponent-scanに[use-default-filters="false"]を付与してみる。ちなみに[use-default-filters]はデフォルトで"true"である。

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">
	<context:component-scan base-package="org.yyama.hoge"
		use-default-filters="false" />
</beans>

実行結果。

FugaクラスもPiyoクラスも登録されていない。

デフォルトでもある[use-default-filters="true"]を指定するとbase-packageに指定したパッケージ配下の@Component/@Repository/@Service/@Controllerが指定されたクラスをコンテナに登録する。一方、"false"とするとそれらを無効にする。すなわち何も登録しないということになる。したがって、[use-default-filters="false"]を指定した場合は、[include-filter]を使用して明示的に登録するクラスを指定しなければいけない。

長くなりそうなので、記事を分ける。

続きはこちら【Spring Framework】component-scanのいろいろ②


Spring 関連記事へのリンク集つくりました。