web-dev-qa-db-ja.com

複数の構成クラスを持つ@ComponentScan:アノテーションベースの構成

春のドキュメントに従って

@Configurationクラスで使用するコンポーネントスキャンディレクティブを構成します。 Spring XMLの<context:component-scan>要素と並行してサポートを提供します。

私の春のWebアプリケーションには、春のコンテナに@Configuration Beanを登録するために、@componentとマークされたファイルが複数あります-

Question1-@ComponentScanを使用できますかいずれか@Configurationクラスまたは全体@Configurationクラス?

質問2-

春にも見た doc

@Configuration
@ComponentScan(basePackageClasses = { MyConfiguration.class })
public class MyConfiguration extends WebMvcConfigurerAdapter {
...
}

ここで構成クラス自体をスキャンする理由。

編集:@ComponentScanの基本的な理解は、ステレオタイプBeanをスキャンして登録することです(ex- @componant@Controller@Servicesなど...)、なぜ@Configuration Bean。

8
user4768611

質問1について-

はい、あなたは@ComponentScanを使用してBeanを登録できます構成Bean春のコンテナ。次のいずれかの方法でコンテナにBeanを登録できます-

  1. rootcontextまたはdispatchersevletcontext@Configuration Beanを登録するには。
  2. これを@ConfigurationをBeanにインポートするには、すでにコンテナに登録されています。

あなたがコンポーネントをスキャンしているMvcConfigクラスがあるとしましょう-

@ComponentScan(basePackages = {"xxxx","yyyy","zzzz"})
@Configuration
public class MvcConfig  {
....
}

MvcConfigをコンテナーに登録するには、

どちらか

new AnnotationConfigWebApplicationContext().register(MvcConfig.class);

または

new AnnotationConfigWebApplicationContext().register(AnotherConfig.class);

@Configuration
@Import({MvcConfig.class})
public class AnotherConfig  {
....
}

質問2について-

ここで、springはMyConfiguration.classを登録するだけでなく、MyConfigurationが定義されているパッケージに存在するすべてのコンポーネントクラスも登録しています。

7
TheCurious

質問1の解決策:
はい、_@Componentscan_は多くの構成クラスで使用できます。それはあなた次第です。特定のパッケージのさまざまな注釈付きクラスをBeanとして登録するだけです。だからあなたが持っているなら すべて _@Componentscan_を1つだけ使用してスキャンされた注釈付きクラスコンポーネント それは十分です、必要なすべてのBeanがアクティブ化され、DispatcherServletコンテナに登録されているため。

質問2の解決策:

_@Configuration
@ComponentScan(basePackageClasses = { MyConfiguration.class })
public class MyConfiguration extends WebMvcConfigurerAdapter {
...
}
_

あなたの質問: なぜここで構成クラス自体をスキャンするのですか?
この@ComponentScan(basePackageClasses = { MyConfiguration.class })は、例としてMyConfiguration.classについて言及しています。問題は、これが何を意味するのかということです。

componentscanパッケージには、basepackage属性またはbasepackageclassesの2つの方法があります。これら2つは同じですが、basepackageclassesを使用すると次の2つの利点があります。
タイプセーフであり、IDE今後のリファクタリングのサポートを追加します
つまり、将来、一部のベースバッケージの名前を(リファクタリングによって)変更できるようになります。ベースパッケージの名前を変更したので、使用した場合、構成クラスの@ComponentScanを変更する必要はありません。 basepackageclasses属性。

次に、2番目の質問に戻ります。 MyConfiguration.classが_@Componentscan_のbasepackageclasses属性の値として指定されているのはなぜですか?

まず、これをお知らせください。
basepackageclasses属性は、いくつかのマーカークラスを表す文字列値を取ります。そのMarkerクラスは次のように伝えています。 おい!このクラスを含む、このクラスが含まれるパッケージにあるすべてのクラスを登録します。

したがって、ここでの回答では、MyConfiguration.classが存在するパッケージに存在するすべてのクラスがコンポーネントスキャンされます。

したがって、Myconfiguration.classは 構成 クラスだけでなく マーカー クラスからコンポーネントへの他のクラスもスキャンします。これは、@ Configurationアノテーションが付けられているMyConfiguration.classを含め、MyConfiguration.classが存在するパッケージに存在するすべてのアノテーション付きクラスが登録されることも意味します。

basepackageclasses属性には、_com.abc.org.Marker.class_などの他のクラスも含めることができます

メリット:
そのため、パッケージの名前を変更しても、Springがパッケージを見つけるのに役立つマーカークラスがあるため、問題はありません。これらのマーカークラスは、パッケージを検索するためのマーカーとして機能するだけなので、内部にコンテンツがある場合とない場合があります。

1

ドキュメントから:

Q1:

@Configurationは@Componentでメタ注釈が付けられているため、@ Configurationクラスはコンポーネントスキャンの候補であり(通常はSpring XMLの要素を使用)、したがって、通常の@Componentと同様に@ Autowired/@ Injectを利用することもできます。

@Configurationクラスは、コンポーネントスキャンを使用してブートストラップされるだけでなく、@ ComponentScanを使用してコンポーネントスキャン自体を構成することもできますアノテーション:

@Configuration
@ComponentScan("com.acme.app.services")
public class AppConfig {
 // various @Bean definitions ...
}

Q2:

basePackageClasses

public abstract Class<?>[] basePackageClasses

注釈付きコンポーネントをスキャンするパッケージを指定するためのbasePackages()のタイプセーフな代替手段。 指定された各クラスのパッケージがスキャンされます


編集した質問の回答

ある時点で、アプリに必要なBeanがどこにあるかをSpringに伝える必要があります。たとえば、次のように使用できます。

public static void main(String[] args) {  
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
    ctx.scan("com.acme");  
    ctx.refresh();
    MyService myService = ctx.getBean(MyService.class);
}

または古いxmlスタイルを使用:

<context:component-scan base-package="com.acme" />

@ConfigurationScanを@Configurationレベルで使用すると、その構成クラスのすべての依存関係が確実に利用できるようになります。 @CompenentScanをbasePackageClassesで使用すると、指定したクラスと同じパッケージで利用可能なすべてのコンポーネントが登録されます。

スキャンする必要があるパッケージを別の場所または方法でSpringにすでに通知している場合は、それを使用する必要はありません。 Q2のコードは、Springが実行できることのほんの一例です。

0
alfcope