クラスパススキャンと管理対象コンポーネント

この章のほとんどの例では、XML を使用して、Spring コンテナー内の各 BeanDefinition を生成する構成メタデータを指定します。前のセクション ( アノテーションベースのコンテナー構成 ) では、ソースレベルのアノテーションを通じて多くの構成メタデータを提供する方法を示しています。ただし、これらの例でも、「ベース」の Bean 定義は XML ファイルで明示的に定義されていますが、アノテーションは依存性注入のみを駆動します。このセクションでは、クラスパスをスキャンして候補コンポーネントを暗黙的に検出するオプションについて説明します。候補コンポーネントは、フィルター条件に一致するクラスであり、対応する Bean 定義がコンテナーに登録されています。これにより、XML を使用して Bean 登録を実行する必要がなくなります。代わりに、アノテーション ( @Component など)、AspectJ 型の式、または独自のカスタムフィルター条件を使用して、コンテナーに登録されている Bean 定義を持つクラスを選択できます。

XML ファイルを使用するのではなく、Java を使用して Bean を定義できます。これらの機能の使用方法の例については、@Configuration@Bean@Import@DependsOn アノテーションを参照してください。

@Component およびその他のステレオタイプアノテーション

@Repository アノテーションは、リポジトリ (データアクセスオブジェクトまたは DAO とも呼ばれます) のロールまたはステレオタイプを満たすクラスのマーカーです。このマーカーの用途には、例外変換で説明されている例外の自動変換があります。

Spring は、さらなるステレオタイプアノテーション @Component@Service@Controller を提供します。@Component は、Spring が管理するコンポーネントの一般的なステレオタイプです。@Repository@Service@Controller は、より具体的なユースケース (それぞれ永続層、サービス層、プレゼンテーション層) に特化した @Component です。コンポーネントクラスに @Component のアノテーションを付けることもできますが、代わりに @Repository@Service、または @Controller のアノテーションを付けることによって、クラスはツールによる処理やアスペクトとの関連付けにより適切に適合します。例: これらのステレオタイプのアノテーションは、ポイントカットの理想的なターゲットになります。@Repository@Service@Controller は、Spring Framework の将来のリリースで追加のセマンティクスも搭載される可能性があります。サービス層に @Component と @Service のどちらを使用するかを選択する場合は、明らかに @Service の方が良い選択です。同様に、前述したように、@Repository は永続層での自動例外変換のマーカーとしてすでにサポートされています。

メタアノテーションと合成アノテーションの使用

Spring が提供するアノテーションの多くは、独自のコードでメタアノテーションとして使用できます。メタアノテーションは、別のアノテーションに適用できるアノテーションです。例: 前出の @Service アノテーションは、次の例に示すように、@Component でメタアノテーションが付けられています。

  • Java

  • Kotlin

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component (1)
public @interface Service {

	// ...
}
1@Component により、@Service は @Component と同じ方法で処理されます。
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
@Component (1)
annotation class Service {

	// ...
}
1@Component により、@Service は @Component と同じ方法で処理されます。

メタアノテーションを組み合わせて「合成アノテーション」を作成することもできます。例: Spring MVC からの @RestController アノテーションは、@Controller と @ResponseBody で構成されます。

さらに、構成されたアノテーションは、必要に応じてメタアノテーションから属性を再宣言して、カスタマイズを可能にすることができます。これは、メタアノテーションの属性のサブセットのみを公開する場合に特に役立ちます。例: Spring の @SessionScope アノテーションは、スコープ名を session にハードコードしますが、それでも proxyMode のカスタマイズを許可します。次のリストは、SessionScope アノテーションの定義を示しています。

  • Java

  • Kotlin

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Scope(WebApplicationContext.SCOPE_SESSION)
public @interface SessionScope {

	/**
	 * Alias for {@link Scope#proxyMode}.
	 * <p>Defaults to {@link ScopedProxyMode#TARGET_CLASS}.
	 */
	@AliasFor(annotation = Scope.class)
	ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;

}
@Target(AnnotationTarget.TYPE, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
@Scope(WebApplicationContext.SCOPE_SESSION)
annotation class SessionScope(
		@get:AliasFor(annotation = Scope::class)
		val proxyMode: ScopedProxyMode = ScopedProxyMode.TARGET_CLASS
)

その後、proxyMode を次のように宣言せずに @SessionScope を使用できます。

  • Java

  • Kotlin

@Service
@SessionScope
public class SessionScopedService {
	// ...
}
@Service
@SessionScope
class SessionScopedService {
	// ...
}

次の例に示すように、proxyMode の値をオーバーライドすることもできます。

  • Java

  • Kotlin

@Service
@SessionScope(proxyMode = ScopedProxyMode.INTERFACES)
public class SessionScopedUserService implements UserService {
	// ...
}
@Service
@SessionScope(proxyMode = ScopedProxyMode.INTERFACES)
class SessionScopedUserService : UserService {
	// ...
}

詳細については、Spring アノテーションプログラミングモデル [GitHub] (英語) wiki ページを参照してください。

クラスの自動検出と Bean 定義の登録

Spring は、ステレオタイプ化されたクラスを自動的に検出し、対応する BeanDefinition インスタンスを ApplicationContext に登録できます。例: 次の 2 つのクラスは、このような自動検出の対象です。

  • Java

  • Kotlin

@Service
public class SimpleMovieLister {

	private MovieFinder movieFinder;

	public SimpleMovieLister(MovieFinder movieFinder) {
		this.movieFinder = movieFinder;
	}
}
@Service
class SimpleMovieLister(private val movieFinder: MovieFinder)
  • Java

  • Kotlin

@Repository
public class JpaMovieFinder implements MovieFinder {
	// implementation elided for clarity
}
@Repository
class JpaMovieFinder : MovieFinder {
	// implementation elided for clarity
}

これらのクラスを自動検出して対応する Bean を登録するには、@ComponentScan を @Configuration クラスに追加する必要があります。basePackages 属性は 2 つのクラスの共通の親パッケージです。(または、各クラスの親パッケージを含むコンマ区切り、セミコロン区切り、スペース区切りのリストを指定できます。)

  • Java

  • Kotlin

@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig  {
	// ...
}
@Configuration
@ComponentScan(basePackages = ["org.example"])
class AppConfig  {
	// ...
}
簡潔にするために、前の例ではアノテーションの value 属性(つまり @ComponentScan("org.example"))を使用できます。

次の代替方法では 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
		https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context
		https://www.springframework.org/schema/context/spring-context.xsd">

	<context:component-scan base-package="org.example"/>

</beans>
<context:component-scan> を使用すると、<context:annotation-config> の機能が暗黙的に有効になります。<context:component-scan> を使用する場合、通常 <context:annotation-config> 要素を含める必要はありません。

クラスパスパッケージをスキャンするには、対応するディレクトリエントリがクラスパスに存在する必要があります。Ant を使用して JAR をビルドする場合は、JAR タスクのファイルのみのスイッチをアクティブにしないでください。また、一部の環境では、セキュリティポリシーに基づいてクラスパスディレクトリが公開されない場合があります。たとえば、JDK 1.7.0_45 以降のスタンドアロンアプリ(マニフェストで 'Trusted-Library' の設定が必要です。stackoverflow.com/questions/19394570/java-jre-7u45-breaks-classloader-getresources (英語) を参照してください)。

JDK 9 のモジュールパス(Jigsaw)では、Spring のクラスパススキャンは通常期待どおりに機能します。ただし、コンポーネントクラスが module-info 記述子でエクスポートされていることを確認してください。Spring がクラスの非パブリックメンバーを呼び出すことが予想される場合は、それらが「開かれている」ことを確認してください(つまり、module-info 記述子で exports 宣言の代わりに opens 宣言を使用する)。

さらに、コンポーネントスキャン要素を使用すると、AutowiredAnnotationBeanPostProcessor と CommonAnnotationBeanPostProcessor の両方が暗黙的に含まれます。つまり、2 つのコンポーネントは自動的に検出され、相互に接続されます。すべて XML で提供される Bean 構成メタデータはありません。

false の値を持つ annotation-config 属性を含めることにより、AutowiredAnnotationBeanPostProcessor および CommonAnnotationBeanPostProcessor の登録を無効にできます。

フィルターを使用してスキャンをカスタマイズする

デフォルトでは、@Component@Repository@Service@Controller@Configuration でアノテーションが付けられたクラス、または @Component でアノテーションが付けられたカスタムアノテーションのみが検出された候補コンポーネントです。ただし、カスタムフィルターを適用することにより、この動作を変更および拡張できます。@ComponentScan アノテーションの includeFilters または excludeFilters 属性として(または XML 構成の <context:component-scan> 要素の <context:include-filter /> または <context:exclude-filter /> 子要素として)追加します。各フィルター要素には、type および expression 属性が必要です。次の表で、フィルタリングオプションについて説明します。

表 1: 型のフィルター
フィルタータイプ 式の例 説明

アノテーション (default)

org.example.SomeAnnotation

ターゲットコンポーネントの型レベルで存在またはメタ表示するアノテーション。

assignable

org.example.SomeClass

ターゲットコンポーネントが割り当てられる(拡張または実装する)クラス(またはインターフェース)。

aspectj

org.example..*Service+

ターゲットコンポーネントによって照合される AspectJ 型式。

regex

org\.example\.Default.*

ターゲットコンポーネントのクラス名と一致する正規表現。

custom

org.example.MyTypeFilter

org.springframework.core.type.TypeFilter インターフェースのカスタム実装。

次の例は、すべての @Repository アノテーションを無視し、代わりに「スタブ」リポジトリを使用する構成を示しています。

  • Java

  • Kotlin

@Configuration
@ComponentScan(basePackages = "org.example",
		includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"),
		excludeFilters = @Filter(Repository.class))
public class AppConfig {
	// ...
}
@Configuration
@ComponentScan(basePackages = ["org.example"],
		includeFilters = [Filter(type = FilterType.REGEX, pattern = [".*Stub.*Repository"])],
		excludeFilters = [Filter(Repository::class)])
class AppConfig {
	// ...
}

次のリストは、同等の XML を示しています。

<beans>
	<context:component-scan base-package="org.example">
		<context:include-filter type="regex"
				expression=".*Stub.*Repository"/>
		<context:exclude-filter type="annotation"
				expression="org.springframework.stereotype.Repository"/>
	</context:component-scan>
</beans>
アノテーションに useDefaultFilters=false を設定するか、<component-scan/> 要素の属性として use-default-filters="false" を指定することにより、デフォルトのフィルターを無効にすることもできます。これにより、@Component@Repository@Service@Controller@RestController または @Configuration でアノテーションが付けられたクラスまたはメタアノテーションが付けられたクラスの自動検出が事実上無効になります。

コンポーネント内での Bean メタデータの定義

Spring コンポーネントは、Bean 定義メタデータをコンテナーに提供することもできます。これは、@Configuration アノテーション付きクラス内で Bean メタデータを定義するために使用されるのと同じ @Bean アノテーションを使用して行うことができます。次の例は、その方法を示しています。

  • Java

  • Kotlin

@Component
public class FactoryMethodComponent {

	@Bean
	@Qualifier("public")
	public TestBean publicInstance() {
		return new TestBean("publicInstance");
	}

	public void doWork() {
		// Component method implementation omitted
	}
}
@Component
class FactoryMethodComponent {

	@Bean
	@Qualifier("public")
	fun publicInstance() = TestBean("publicInstance")

	fun doWork() {
		// Component method implementation omitted
	}
}

上記のクラスは、doWork() メソッドにアプリケーション固有のコードを持つ Spring コンポーネントです。ただし、メソッド publicInstance() を参照するファクトリメソッドを持つ Bean 定義にも貢献します。@Bean アノテーションは、ファクトリメソッドおよびその他の Bean 定義プロパティ(@Qualifier アノテーションによる修飾子値など)を識別します。指定できるその他のメソッドレベルのアノテーションは、@Scope@Lazy、カスタム修飾子アノテーションです。

コンポーネントの初期化のロールに加えて、@Autowired または @Inject でマークされたインジェクションポイントに @Lazy アノテーションを配置することもできます。このコンテキストでは、レイジー解決プロキシの注入につながります。ただし、このようなプロキシアプローチはかなり制限されています。洗練された怠惰な相互作用、特にオプションの依存関係との組み合わせでは、代わりに ObjectProvider<MyTargetBean> をお勧めします。

前述のように、@Bean メソッドのオートワイヤーの追加サポートとともに、オートワイヤーフィールドとメソッドがサポートされています。次の例は、その方法を示しています。

  • Java

  • Kotlin

@Component
public class FactoryMethodComponent {

	private static int i;

	@Bean
	@Qualifier("public")
	public TestBean publicInstance() {
		return new TestBean("publicInstance");
	}

	// use of a custom qualifier and autowiring of method parameters
	@Bean
	protected TestBean protectedInstance(
			@Qualifier("public") TestBean spouse,
			@Value("#{privateInstance.age}") String country) {
		TestBean tb = new TestBean("protectedInstance", 1);
		tb.setSpouse(spouse);
		tb.setCountry(country);
		return tb;
	}

	@Bean
	private TestBean privateInstance() {
		return new TestBean("privateInstance", i++);
	}

	@Bean
	@RequestScope
	public TestBean requestScopedInstance() {
		return new TestBean("requestScopedInstance", 3);
	}
}
@Component
class FactoryMethodComponent {

	companion object {
		private var i: Int = 0
	}

	@Bean
	@Qualifier("public")
	fun publicInstance() = TestBean("publicInstance")

	// use of a custom qualifier and autowiring of method parameters
	@Bean
	protected fun protectedInstance(
			@Qualifier("public") spouse: TestBean,
			@Value("#{privateInstance.age}") country: String) = TestBean("protectedInstance", 1).apply {
		this.spouse = spouse
		this.country = country
	}

	@Bean
	private fun privateInstance() = TestBean("privateInstance", i++)

	@Bean
	@RequestScope
	fun requestScopedInstance() = TestBean("requestScopedInstance", 3)
}

この例では、String メソッドパラメーター country を、privateInstance という名前の別の Bean の age プロパティの値に自動接続します。Spring Expression Language エレメントは、表記 #{ <expression> } を介してプロパティの値を定義します。@Value アノテーションの場合、式テキストを解決するときに Bean 名を検索するように式リゾルバーが事前構成されています。

Spring Framework 4.3 以降では、型 InjectionPoint (またはそのより具象サブクラス: DependencyDescriptor)のファクトリメソッドパラメーターを宣言して、現在の Bean の作成をトリガーするリクエストしているインジェクションポイントにアクセスすることもできます。これは、Bean インスタンスの実際の作成にのみ適用され、既存のインスタンスの挿入には適用されないことに注意してください。結果として、この機能はプロトタイプスコープの Bean に最も意味があります。他のスコープの場合、ファクトリメソッドは、指定されたスコープで新しい Bean インスタンスの作成をトリガーしたインジェクションポイントのみを確認します(たとえば、遅延シングルトン Bean の作成をトリガーした依存関係)。このようなシナリオでは、提供されたインジェクションポイントメタデータをセマンティックケアで使用できます。次の例は、InjectionPoint の使用方法を示しています。

  • Java

  • Kotlin

@Component
public class FactoryMethodComponent {

	@Bean @Scope("prototype")
	public TestBean prototypeInstance(InjectionPoint injectionPoint) {
		return new TestBean("prototypeInstance for " + injectionPoint.getMember());
	}
}
@Component
class FactoryMethodComponent {

	@Bean
	@Scope("prototype")
	fun prototypeInstance(injectionPoint: InjectionPoint) =
			TestBean("prototypeInstance for ${injectionPoint.member}")
}

通常の Spring コンポーネントの @Bean メソッドは、Spring @Configuration クラス内の対応する @Bean メソッドとは異なる方法で処理されます。違いは、@Component クラスがメソッドとフィールドの呼び出しをインターセプトするために CGLIB で拡張されていないことです。CGLIB プロキシは、@Configuration クラスの @Bean メソッド内のメソッドまたはフィールドを呼び出すことにより、コラボレーションオブジェクトへの Bean メタデータ参照を作成する手段です。このようなメソッドは、通常の Java セマンティクスで呼び出されるのではなく、@Bean メソッドのプログラム呼び出しで他の Bean を参照する場合でも、Spring Bean の通常のライフサイクル管理とプロキシを提供するためにコンテナーを通過します。対照的に、プレーン @Component クラス内の @Bean メソッドでメソッドまたはフィールドを呼び出すには、標準の Java セマンティクスがあり、特別な CGLIB 処理やその他の制約は適用されません。

@Bean メソッドを static として宣言すると、含む構成クラスをインスタンスとして作成せずに呼び出すことができます。これは、ポストプロセッサー Bean(たとえば、型 BeanFactoryPostProcessor または BeanPostProcessor)を定義するときに特に意味があります。そのような Bean は、コンテナーライフサイクルの初期に初期化され、その時点で構成の他の部分をトリガーしないようにする必要があるためです

静的な @Bean メソッドの呼び出しは、技術的な制限のため、コンテナーによって(このセクションで前述したように) @Configuration クラス内でさえもインターセプトされません。CGLIB サブクラス化は、非静的メソッドのみをオーバーライドできます。その結果、別の @Bean メソッドへの直接呼び出しには標準の Java セマンティクスがあり、その結果、独立したインスタンスがファクトリメソッド自体から直接返されます。

@Bean メソッドの Java 言語の可視性は、Spring のコンテナーで生成される Bean 定義に直接的な影響を与えません。@Configuration 以外のクラスに収まると思われるように、またどこにいても静的メソッドに適合するように、ファクトリメソッドを自由に宣言できます。ただし、@Configuration クラスの通常の @Bean メソッドはオーバーライド可能である必要があります。つまり、private または final として宣言してはなりません。

@Bean メソッドは、特定のコンポーネントまたは構成クラスの基本クラス、およびコンポーネントまたは構成クラスによって実装されるインターフェースで宣言された Java 8 デフォルトメソッドでも検出されます。これにより、Spring 4.2 以降の Java 8 のデフォルトのメソッドを使用して複数の継承も可能になり、複雑な構成の配置を柔軟に構成できます。

最後に、実行時に利用可能な依存関係に応じて使用する複数のファクトリメソッドの配置として、単一のクラスが同じ Bean に対して複数の @Bean メソッドを保持する場合があります。これは、他の構成シナリオで「最も貪欲な」コンストラクターまたはファクトリメソッドを選択する場合と同じアルゴリズムです。コンテナーが複数の @Autowired コンストラクターを選択する方法に類似して、充足可能な依存関係の数が最も多いバリアントが構築時に選択されます。

自動検出されたコンポーネントの命名

コンポーネントがスキャンプロセスの一部として自動検出されると、そのスキャナーに認識されている BeanNameGenerator 戦略によってその Bean 名が生成されます。

デフォルトでは、AnnotationBeanNameGenerator が使用されます。Spring ステレオタイプアノテーションの場合、アノテーションの value 属性を介して名前を指定すると、その名前は対応する Bean 定義の名前として使用されます。この規則は、Spring ステレオタイプアノテーションの代わりに JSR-250 および JSR-330 アノテーションが使用される場合にも適用されます: @jakarta.annotation.ManagedBean@javax.annotation.ManagedBean@jakarta.inject.Named@javax.inject.Named

Spring Framework 6.1 以降、Bean 名の指定に使用されるアノテーション属性の名前は value である必要はなくなりました。カスタムステレオタイプアノテーションでは、別の名前 ( name など) で属性を宣言し、その属性に @AliasFor(annotation = Component.class, attribute = "value") のアノテーションを付けることができます。具体的な例については、ControllerAdvice#name() のソースコード宣言を参照してください。

Spring Framework 6.1 の時点で、規則に基づくステレオタイプ名のサポートは非推奨となり、フレームワークの将来のバージョンでは削除される予定です。カスタムステレオタイプアノテーションは、@AliasFor を使用して、@Component の value 属性の明示的なエイリアスを宣言する必要があります。具体的な例については、Repository#value() および ControllerAdvice#name() のソースコード宣言を参照してください。

このようなアノテーションやその他の検出されたコンポーネント (カスタムフィルターによって検出されたものなど) から明示的な Bean 名を導出できない場合、デフォルトの Bean 名ジェネレーターは大文字を含まない非修飾クラス名を返します。例: 次のコンポーネントクラスが検出された場合、名前は myMovieLister および movieFinderImpl になります。

  • Java

  • Kotlin

@Service("myMovieLister")
public class SimpleMovieLister {
	// ...
}
@Service("myMovieLister")
class SimpleMovieLister {
	// ...
}
  • Java

  • Kotlin

@Repository
public class MovieFinderImpl implements MovieFinder {
	// ...
}
@Repository
class MovieFinderImpl : MovieFinder {
	// ...
}

デフォルトの Bean 命名戦略に依存したくない場合は、カスタムの Bean 命名戦略を提供できます。まず、BeanNameGenerator (Javadoc) インターフェースを実装し、デフォルトの引数なしのコンストラクターを必ず含めてください。次に、以下のアノテーションの例と Bean 定義が示すように、スキャナーの構成時に完全修飾クラス名を指定します。

修飾されていない同じクラス名を持つ複数の自動検出されたコンポーネント(つまり、名前が同じで異なるパッケージにあるクラス)が原因で名前の競合が発生した場合は、デフォルトで完全修飾クラス名になる BeanNameGenerator を構成する必要があります。生成された Bean 名。Spring Framework 5.2.3 以降、パッケージ org.springframework.context.annotation にある FullyQualifiedAnnotationBeanNameGenerator をそのような目的に使用できます。
  • Java

  • Kotlin

@Configuration
@ComponentScan(basePackages = "org.example", nameGenerator = MyNameGenerator.class)
public class AppConfig {
	// ...
}
@Configuration
@ComponentScan(basePackages = ["org.example"], nameGenerator = MyNameGenerator::class)
class AppConfig {
	// ...
}
<beans>
	<context:component-scan base-package="org.example"
		name-generator="org.example.MyNameGenerator" />
</beans>

一般的な規則として、他のコンポーネントが明示的に参照している場合は、アノテーションで名前を指定することを検討してください。一方、コンテナーが接続を担当する場合は、自動生成された名前で十分です。

自動検出されたコンポーネントのスコープを提供する

一般に Spring 管理コンポーネントと同様に、自動検出されたコンポーネントのデフォルトで最も一般的なスコープは singleton です。ただし、@Scope アノテーションで指定できる別のスコープが必要になる場合があります。次の例に示すように、アノテーション内でスコープの名前を指定できます。

  • Java

  • Kotlin

@Scope("prototype")
@Repository
public class MovieFinderImpl implements MovieFinder {
	// ...
}
@Scope("prototype")
@Repository
class MovieFinderImpl : MovieFinder {
	// ...
}
@Scope アノテーションは、具体的な Bean クラス(アノテーション付きコンポーネントの場合)またはファクトリメソッド(@Bean メソッドの場合)でのみ内省されます。XML Bean 定義とは対照的に、Bean 定義の継承という概念はなく、クラスレベルの継承階層はメタデータの目的には関係ありません。

Spring コンテキストでの「リクエスト」や「セッション」などの Web 固有のスコープの詳細については、リクエスト、セッション、アプリケーション、WebSocket スコープを参照してください。これらのスコープ用に事前に作成されたアノテーションと同様に、Spring のメタアノテーションアプローチを使用して独自のスコープアノテーションを作成することもできます。たとえば、@Scope("prototype") でアノテーションが付けられたカスタムアノテーションメタは、カスタムスコーププロキシモードを宣言することもできます。

アノテーションベースのアプローチに依存するのではなく、スコープ解決のカスタム戦略を提供するために、ScopeMetadataResolver (Javadoc) インターフェースを実装できます。デフォルトの引数なしのコンストラクターを必ず含めてください。次に、以下のアノテーションと Bean 定義の例に示すように、スキャナーの構成時に完全修飾クラス名を指定できます。
  • Java

  • Kotlin

@Configuration
@ComponentScan(basePackages = "org.example", scopeResolver = MyScopeResolver.class)
public class AppConfig {
	// ...
}
@Configuration
@ComponentScan(basePackages = ["org.example"], scopeResolver = MyScopeResolver::class)
class AppConfig {
	// ...
}
<beans>
	<context:component-scan base-package="org.example" scope-resolver="org.example.MyScopeResolver"/>
</beans>

特定の非シングルトンスコープを使用する場合、スコープオブジェクトのプロキシを生成する必要がある場合があります。推論は依存関係としてのスコープ Bean で説明されています。この目的のために、scoped-proxy 属性を component-scan 要素で使用できます。可能な 3 つの値は次のとおりです。nointerfacestargetClass。例: 次の構成では、標準の JDK 動的プロキシが生成されます。

  • Java

  • Kotlin

@Configuration
@ComponentScan(basePackages = "org.example", scopedProxy = ScopedProxyMode.INTERFACES)
public class AppConfig {
	// ...
}
@Configuration
@ComponentScan(basePackages = ["org.example"], scopedProxy = ScopedProxyMode.INTERFACES)
class AppConfig {
	// ...
}
<beans>
	<context:component-scan base-package="org.example" scoped-proxy="interfaces"/>
</beans>

アノテーション付きの修飾子メタデータの提供

@Qualifier アノテーションについては、修飾子を使用したアノテーションベースのオートワイヤーの微調整で説明しています。そのセクションの例では、@Qualifier アノテーションとカスタム修飾子アノテーションを使用して、オートワイヤーの候補を解決するときにきめ細かな制御を提供します。これらの例は XML Bean 定義に基づいているため、XML の bean 要素の qualifier または meta 子要素を使用して、候補の Bean 定義に修飾子メタデータが提供されました。コンポーネントの自動検出をクラスパススキャンに依存している場合、候補クラスの型レベルのアノテーションを修飾子メタデータに提供できます。次の 3 つの例は、この手法を示しています。

  • Java

  • Kotlin

@Component
@Qualifier("Action")
public class ActionMovieCatalog implements MovieCatalog {
	// ...
}
@Component
@Qualifier("Action")
class ActionMovieCatalog : MovieCatalog
  • Java

  • Kotlin

@Component
@Genre("Action")
public class ActionMovieCatalog implements MovieCatalog {
	// ...
}
@Component
@Genre("Action")
class ActionMovieCatalog : MovieCatalog {
	// ...
}
  • Java

  • Kotlin

@Component
@Offline
public class CachingMovieCatalog implements MovieCatalog {
	// ...
}
@Component
@Offline
class CachingMovieCatalog : MovieCatalog {
	// ...
}
ほとんどのアノテーションベースの代替方法と同様に、XML を使用すると、同じ型の複数の Bean が修飾子メタデータのバリエーションを提供できる一方で、アノテーションメタデータはクラス定義自体にバインドされることに留意してください。クラスごとではなくインスタンス。