Java Config @Bean не подключен автоматически в другом классе @Configuration

Пытаясь настроить веб-приложение Spring 4 с помощью Java Config, я сталкиваюсь с проблемой автоматического подключения bean-компонента, созданного в классе конфигурации, к другому классу конфигурации. Бин dataSource имеет нулевое значение в классе MyBatisConfig. Кажется, это единственный компонент в конфигурации, который не подключен должным образом. Глядя на журналы отладки Spring (см. Последнюю часть журналов в последнем блоке кода ниже), он выглядит должным образом, но также, кажется, уничтожен ?. Что может быть не так в моей конфигурации?

Класс PropertySourcesPlaceholderConfigurerConfig:

package nl.somesite.teamshot.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.ClassPathResource;

@Configuration
public class PropertySourcesPlaceholderConfigurerConfig {

    @Bean
    public PropertySourcesPlaceholderConfigurer propertyConfigurer() {
        PropertySourcesPlaceholderConfigurer propertyConfigurer = new PropertySourcesPlaceholderConfigurer();

        propertyConfigurer.setLocation(new ClassPathResource("application.properties"));
        /*propertyConfigurer.setLocation(new ClassPathResource("file:${catalina.home}/conf/application.properties"));
        propertyConfigurer.setLocation(new ClassPathResource("/var/lib/openshift/517874b8e0b8cd218e000391/app-root/data/apache-tomcat-7.0.39/conf/application.properties"));*/

        propertyConfigurer.setIgnoreUnresolvablePlaceholders(false);
        propertyConfigurer.setIgnoreResourceNotFound(true);
        return propertyConfigurer;
    }

}

Класс DbConfig:

package nl.somesite.teamshot.config;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import({PropertySourcesPlaceholderConfigurerConfig.class})
public class DbConfig {

    private @Value("jdbc:mysql://${OPENSHIFT_MYSQL_DB_HOST}:${OPENSHIFT_MYSQL_DB_PORT}/${OPENSHIFT_MYSQL_DATABASE}") String url;
    private @Value("${OPENSHIFT_MYSQL_DB_USERNAME}") String username;
    private @Value("${OPENSHIFT_MYSQL_DB_PASSWORD}") String password;

    static Logger log = LogManager.getLogger(DbConfig.class.getName());

    @Bean
    public BasicDataSource dataSource() {
        log.debug("Creating dataSource bean, url =  "+ url);

        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setDefaultAutoCommit(false);

        log.debug("dataSource bean url = "+ dataSource.getUrl());
        return dataSource;
    }

}

Класс MyBatisConfig:

package nl.somesite.teamshot.config;
import java.io.IOException;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

@Configuration
@Import({DbConfig.class})
public class MyBatisConfig {

    @Autowired private BasicDataSource dataSource;


    static Logger log = LogManager.getLogger(MyBatisConfig.class.getName());

    @Bean
    public SqlSessionFactoryBean sqlSessionFactory() {
        log.debug("Creating SqlSessionFactoryBean, dataSource = " + dataSource);

        SqlSessionFactoryBean sqlSessionFactory =  new SqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

        org.springframework.core.io.Resource[] classPathResources;
        try {
            classPathResources = resolver.getResources("classpath*:/mappers/*.xml");
            sqlSessionFactory.setMapperLocations(classPathResources);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return sqlSessionFactory;
    }

    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
        log.debug("Creating MapperScannerConfigurer");
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setBasePackage("nl.somesite.teamshot.data");
        return mapperScannerConfigurer;
    }

}

Класс AppConfig:

package nl.somesite.teamshot.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = {"nl.somesite.teamshot.config"})
public class AppConfig {

}

Класс AppInitializer:

package nl.somesite.teamshot.initializer;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

public class AppInitializer implements WebApplicationInitializer {

    private static final String CONFIG_LOCATION = "nl.somesite.teamshot.config";
    private static final String MAPPING_URL = "/";

    static Logger log = LogManager.getLogger(AppInitializer.class.getName());

    public void onStartup(ServletContext servletContext) throws ServletException {
        WebApplicationContext context = getContext();
        servletContext.addListener(new ContextLoaderListener(context));
        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet", new DispatcherServlet(context));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping(MAPPING_URL);
    }

    private AnnotationConfigWebApplicationContext getContext() {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.setConfigLocation(CONFIG_LOCATION);
        return context;
    }

}

Класс WebMvcConfig:

package nl.somesite.teamshot.config;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;


@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {


    static Logger log = LogManager.getLogger(WebMvcConfig.class.getName());

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Bean
    public ViewResolver internalResourceViewResolver() {
        InternalResourceViewResolver resolver =  new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

}

Последняя часть логов:

[DEBUG:] 2014-07-09 01:25:20 [DefaultSingletonBeanRegistry line:220] Creating shared instance of singleton bean 'dataSource'  
    [DEBUG:] 2014-07-09 01:25:20 [AbstractAutowireCapableBeanFactory line:449] Creating instance of bean 'dataSource'  
    [DEBUG:] 2014-07-09 01:25:20 [AbstractBeanFactory line:249] Returning cached instance of singleton bean 'dbConfig'  
    [DEBUG:] 2014-07-09 01:25:20 [DbConfig line:25] Creating dataSource bean, url =  jdbc:mysql://localhost:3306/teamshot?useUnicode=true&characterEncoding=UTF-8  
    [DEBUG:] 2014-07-09 01:25:20 [DbConfig line:34] dataSource bean url = jdbc:mysql://localhost:3306/teamshot?useUnicode=true&characterEncoding=UTF-8  
    [DEBUG:] 2014-07-09 01:25:20 [AbstractAutowireCapableBeanFactory line:523] Eagerly caching bean 'dataSource' to allow for resolving potential circular references  
    [DEBUG:] 2014-07-09 01:25:20 [AbstractAutowireCapableBeanFactory line:477] Finished creating instance of bean 'dataSource'  
    [DEBUG:] 2014-07-09 01:25:20 [DefaultSingletonBeanRegistry line:220] Creating shared instance of singleton bean 'sqlSessionFactory'  
    [DEBUG:] 2014-07-09 01:25:20 [AbstractAutowireCapableBeanFactory line:449] Creating instance of bean 'sqlSessionFactory'  
    [DEBUG:] 2014-07-09 01:25:20 [AbstractBeanFactory line:249] Returning cached instance of singleton bean 'myBatisConfig'  
    [DEBUG:] 2014-07-09 01:25:20 [MyBatisConfig line:27] Creating SqlSessionFactoryBean, dataSource = null  
    [DEBUG:] 2014-07-09 01:25:20 [PathMatchingResourcePatternResolver line:553] Looking for matching resources in directory tree [D:\Eclipse workspaces\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\teamshot\WEB-INF\classes\mappers]  
    [DEBUG:] 2014-07-09 01:25:20 [PathMatchingResourcePatternResolver line:615] Searching directory [D:\Eclipse workspaces\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\teamshot\WEB-INF\classes\mappers] for files matching pattern [D:/Eclipse workspaces/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/teamshot/WEB-INF/classes/mappers/*.xml]  
    [DEBUG:] 2014-07-09 01:25:20 [PathMatchingResourcePatternResolver line:354] Resolved location pattern [classpath*:/mappers/*.xml] to resources [file [D:\Eclipse workspaces\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\teamshot\WEB-INF\classes\mappers\newsitems.xml], file [D:\Eclipse workspaces\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\teamshot\WEB-INF\classes\mappers\teams.xml]]  
    [DEBUG:] 2014-07-09 01:25:20 [AbstractAutowireCapableBeanFactory line:523] Eagerly caching bean 'sqlSessionFactory' to allow for resolving potential circular references  
    [DEBUG:] 2014-07-09 01:25:20 [AbstractAutowireCapableBeanFactory line:1595] Invoking afterPropertiesSet() on bean with name 'sqlSessionFactory'  
    [DEBUG:] 2014-07-09 01:25:20 [DefaultSingletonBeanRegistry line:474] Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@3278a91: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,appConfig,dbConfig,myBatisConfig,propertySourcesPlaceholderConfigurerConfig,webMvcConfig,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor,dataSource,sqlSessionFactory,mapperScannerConfigurer,propertyConfigurer,org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration,requestMappingHandlerMapping,mvcContentNegotiationManager,viewControllerHandlerMapping,beanNameHandlerMapping,resourceHandlerMapping,defaultServletHandlerMapping,requestMappingHandlerAdapter,mvcConversionService,mvcValidator,mvcUriComponentsContributor,httpRequestHandlerAdapter,simpleControllerHandlerAdapter,handlerExceptionResolver,internalResourceViewResolver,newsItemMapper,teamMapper]; root of factory hierarchy  
    [DEBUG:] 2014-07-09 01:25:20 [DisposableBeanAdapter line:322] Invoking destroy method 'close' on bean with name 'dataSource'  
    [DEBUG:] 2014-07-09 01:25:20 [DisposableBeanAdapter line:244] Invoking destroy() on bean with name 'webMvcConfig'  
    [DEBUG:] 2014-07-09 01:25:20 [DisposableBeanAdapter line:244] Invoking destroy() on bean with name 'dbConfig'  
    [DEBUG:] 2014-07-09 01:25:21 [DisposableBeanAdapter line:244] Invoking destroy() on bean with name 'appConfig'  
    [DEBUG:] 2014-07-09 01:25:21 [DisposableBeanAdapter line:244] Invoking destroy() on bean with name 'propertySourcesPlaceholderConfigurerConfig'  
    [ERROR:] 2014-07-09 01:25:21 [ContextLoader line:331] Context initialization failed Error creating bean with name 'sqlSessionFactory' defined in class path resource [nl/somesite/teamshot/config/MyBatisConfig.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Property 'dataSource' is required 
    jul 09, 2014 1:25:21 AM org.apache.catalina.core.StandardContext listenerStart
    SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [nl/somesite/teamshot/config/MyBatisConfig.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Property 'dataSource' is required
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1553)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
        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:681)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
        at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
        at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
        at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
        at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4887)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5381)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
        at java.util.concurrent.FutureTask.run(FutureTask.java:166)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:724)
    Caused by: java.lang.IllegalArgumentException: Property 'dataSource' is required
        at org.springframework.util.Assert.notNull(Assert.java:112)
        at org.mybatis.spring.SqlSessionFactoryBean.afterPropertiesSet(SqlSessionFactoryBean.java:337)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
        ... 22 more

Если я отключаю Spring Debug Logging, я вижу это:

[DEBUG:] 2014-07-09 11:02:19 [MyBatisConfig line:50] Creating MapperScannerConfigurer  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [DbConfig line:24] Creating dataSource bean, url =  jdbc:mysql://localhost:3306/teamshot?useUnicode=true&characterEncoding=UTF-8  
[DEBUG:] 2014-07-09 11:02:20 [DbConfig line:33] dataSource bean url = jdbc:mysql://localhost:3306/teamshot?useUnicode=true&characterEncoding=UTF-8  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[DEBUG:] 2014-07-09 11:02:20 [MyBatisConfig line:30] Creating SqlSessionFactoryBean, dataSource = null  
[ERROR:] 2014-07-09 11:02:20 [ContextLoader line:331] Context initialization failed Error creating bean with name 'sqlSessionFactory' defined in class path resource [nl/somesite/teamshot/config/MyBatisConfig.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Property 'dataSource' is required 

Ответы на вопрос(4)

Ваш ответ на вопрос