古典的なコンテキストをロードしてEclipseでアプリケーションを実行すると、心配する必要はありません。選択したSpringプロファイルに対応するconfigクラスで定義されたBeanが正しくインスタンス化されます。
public class BasketHandlerLoader {
public static void main(String[] args) throws Exception {
@SuppressWarnings("resource")
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:config/spring/spring-archibald-basket-handler-context.xml");
context.registerShutdownHook();
}
}
しかし、Spring Bootでアプリケーションを実行すると、これらのBeanはインスタンス化されません。
@Configuration
@ImportResource("classpath:config/spring/spring-archibald-basket-handler-context.xml")
public class BasketHandlerLoader {
public static void main(String[] args) throws Exception {
SpringApplication.run(BasketHandlerLoader.class, args);
}
}
「dev」SpringプロファイルのJava構成クラスは次のとおりです。
@Configuration
@Profile("dev")
@EnableTransactionManagement
@PropertySources(value = { @PropertySource("classpath:filters/dev.properties") })
public class DevPersistenceConfig extends AbstractPersistenceConfig {
@Inject
private Environment env;
@Override
@Bean
public DataSource dataSource() {
return super.createDataSource(env);
}
@Override
public Properties hibernateProperties() {
return super.createHibernateProperties(env);
}
}
ここでAbstractPersistenceConfigインスタンス化されていない他のBeanを含むクラス:
public abstract class AbstractPersistenceConfig {
// Constants...
// ************************** ABSTRACT METHODS **************************
/**
* Returns a property list containing the Hibernate properties.
*
* @return the Hibernate properties.
*/
public abstract Properties hibernateProperties();
/**
* Defines the application datasource bean corresponding with the current Spring Profile.
*
* @return the application datasource bean corresponding with the current Spring Profile.
*/
@Bean
public abstract DataSource dataSource();
/**
* Defines the Hibernate session factory bean.
*
* @return the {@code LocalSessionFactoryBean}.
*/
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { HIBERNATE_PACKAGE_TO_SCAN });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
/**
* Defines the bean allowing to Hibernate to support the transaction handling mechanism.
*
* @return the {@code HibernateTransactionManager}.
*/
@Bean
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory().getObject());
return txManager;
}
// ************************** PROTECTED METHODS **************************
// ...
// ************************** PRIVATE METHODS **************************
// ...
}
次のコマンドを使用してアプリケーションを実行しようとしましたが、同じ結果になりました。
Java -jar archibald-basket-handler-1.0-SNAPSHOT.jar --spring.profiles.active=dev
Java -jar -Dspring.profiles.active=dev archibald-basket-handler-1.0-SNAPSHOT.jar
具体的には、Bean "sessionFactory"はインスタンス化されておらず、私のGenericDaoImplクラスに注入できません。
スタックトレース:
Java.lang.reflect.InvocationTargetException
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at Java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.Java:53)
at Java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'basketDaoImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.hibernate.SessionFactory fr.ina.archibald.dao.impl.GenericDaoImpl.sessionFactory; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.hibernate.SessionFactory] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.Java:292)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.Java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.Java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.Java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.Java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.Java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.Java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.Java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.Java:703)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.Java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.Java:482)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.Java:648)
at org.springframework.boot.SpringApplication.run(SpringApplication.Java:311)
at org.springframework.boot.SpringApplication.run(SpringApplication.Java:909)
at org.springframework.boot.SpringApplication.run(SpringApplication.Java:898)
at fr.ina.archibald.basket.loader.BasketHandlerLoader.main(BasketHandlerLoader.Java:30)
... 6 more
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.hibernate.SessionFactory fr.ina.archibald.dao.impl.GenericDaoImpl.sessionFactory; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.hibernate.SessionFactory] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.Java:508)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.Java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.Java:289)
... 21 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.hibernate.SessionFactory] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.Java:1103)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.Java:963)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.Java:858)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.Java:480)
... 23 more
SpringBootの親POMなしでSpringBoot1.0.2.RELEASEを使用しています。私はこれをPOMで定義するだけです:
<dependencyManagement>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${org.springframework.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencyManagement>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>${start-class}</mainClass>
</configuration>
</plugin>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
<version>${org.springframework.boot.version}</version>
</dependency>
アイデアはありますか?
どうもありがとう!!
@Import
クラスを直接@Configuration
するか、@ComponentScan
アノテーションを使用する必要があると思います。 ClassPathXmlApplicationContext
を使用する最初の例は、XML処理が早期に行われるため機能し、<component-scan>
は処理される前に@Configuration
クラスを検出します。
2番目の例では、SpringApplication
はすでに@Configuration
クラスの処理を開始しており、XMLは@ImportResource
を介してロードされます。この時点では、XML <component-scan>
で@Configuration
を追加することはできません。
答えを並べ替える:BasketHandlerLoader
クラスで@ComonentScan
を試してください。
すごい!!!できます! Philに大いに感謝します(解決策と説明をありがとう!):-)
@Configuration
@ImportResource("classpath:config/spring/spring-archibald-basket-handler-context.xml")
@ComponentScan(basePackages = { "fr.ina.archibald.dao.config.persistence" }, includeFilters = @ComponentScan.Filter(value = Component.class, type = FilterType.ANNOTATION))
public class BasketHandlerLoader {
public static void main(String[] args) throws Exception {
SpringApplication.run(BasketHandlerLoader.class, args);
}
}