8

applicationContext.xmlクラスパスのルートに次のファイルがあります。

<context:annotation-config />

    <context:property-placeholder location="classpath:props/datasource.properties"  />

    <bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource"
        p:username="${jdbc.username}" 
        p:password="${jdbc.password}" 
        p:url="${jdbc.url}"
        p:driverClassName="${jdbc.driverclass}" 
        p:validationQuery="SELECT sysdate FROM dual" />

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
        p:dataSource-ref="datasource" 
        p:mapperLocations="classpath:mappers/*-mapper.xml" />

    <tx:annotation-driven transaction-manager="txManager" />
    <bean id="txManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
        p:dataSource-ref="datasource" />

    <bean id="mappeScannerConfigurere" class="org.mybatis.spring.mapper.MapperScannerConfigurer"
        p:sqlSessionFactory-ref="sqlSessionFactory" 
        p:basePackage="com.mypackage" />

props/datasource.properties次のような内容のクラスパスのルートにも存在します。

jdbc.url=myjdbcurl
jdbc.driverclass=myClass
jdbc.username=myUserName
jdbc.password=myPassword

次の注釈を介して前述の applicationContext.xml を使用することを宣言するスプリング マネージド テストがあります。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})

テストメソッドを呼び出すと、春から次のエラーが発生します:

org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class '${jdbc.driverclass}'

私が理解しているように、spingはjdbc.driverclassへの参照を解決しませんでした。私は何を間違えましたか?

PS:春の 3.2.3.RELEASE を使用しています

**

編集

**

おそらく、問題は にある可能性がありますMapperScannerConfigurerBeanDefinitionRegistryPostProcessorJavadocが言うように、それはおよびです:

標準の BeanFactoryPostProcessor SPI の拡張。通常の BeanFactoryPostProcessor 検出が開始される前に、さらに Bean 定義を登録できます 。

そのため、 sqlSessionFactoryMapperScannerConfigurerを介してデータソース オブジェクトをインスタンス化しますBeanFacoryPostProcessor(を担当する<context:property-placeholder/>) は使用されていません。私の質問は、 and ( )BeanFacoryPostProcessorから並べ替える方法に変わりますか?<context:property-placeholder/>BeanDefinitionRegistryPostProcessorMapperScannerConfigurer

解決済み

数時間の調査の後、私は解決策を見つけました:


先に述べたようMapperScannerConfigurerに、 は のBeanDefinitionRegistryPostProcessor前に発生しBeanFactoryPostProcessor、 は の責任を負い<context:property-placeholder/>ます。そのため、MapperScannerConfigurer の作成中、外部プロパティへの参照は解決されません。この場合、データソースの作成をBeanFactoryPostProcessor適用後まで延期する必要があります。これにはいくつかの方法があります。

  • から削除p:sqlSessionFactory-ref="sqlSessionFactory"MapperScannerConfigurerます。この場合、データソース オブジェクトは の前に作成されるMapperScannerConfigurerのではなく、後で作成さBeanFactoryPostProcessor<context:property-placeholder/>ます。applicationContext に複数の sqlSessionFactory がある場合、いくつかの問題が発生する可能性があります
  • mybatis-spring モジュールのバージョン 1.0.2 以降では、 のsqlSessionFactoryBeanName代わりに設定する可能性がありsqlSessionFactoryます。で PropertyPlaceHolder の問題を解決するのに役立ちますBeanFactoryPostProcessor。mybatis-spring docに記載されているこの問題を解決するための推奨される方法です。
4

2 に答える 2

0

短い形式: BeanDefinitionRegistryPostProcessor の実装をロードする適切な方法は何ですか?

展開された形式: Bean が作成される前に BeanDefinitionRegistryPostProcessor をロードする方法はありますか。javadoc を見ると、次のようになります。

標準の {@link BeanFactoryPostProcessor} SPI の拡張。通常の BeanFactoryPostProcessor 検出が開始される前に、さらに Bean 定義を登録できます。

そのため、Bean 定義が作成されたときに、Bean が作成される前にロードされることを意図しています。アプリケーションxmlで通常のBeanとして作成すると、そもそもこのBeanを持つ目的が無効になります。

于 2016-03-30T23:37:28.890 に答える