экспоненциально увеличивающееся время запуска (инициализация Spring) для каждого добавленного интерфейса DAO

Во время запуска Spring warn-logging показывает ошибки при создании, например,
«bean с именем 'userRepositoryInterface' ... Не удалось вызвать метод инициализации; вложенное исключение - java.lang.IllegalArgumentException: требуется свойство 'sqlSessionFactory' или 'sqlSessionTemplate' "
В течение следующих нескольких минут это повторяется много раз для каждого RepositoryInterface, но в конце концов проблема решена, и приложение работает нормально. Но время запуска недопустимо. Кроме того, когда я добавил новый RepositoryInterface, время запуска увеличилось до 20 минут, пока на сервере (weblogic 12c) не закончилась память.
Реализующие классы этих RepositoryInterfaces созданы Spring / Mybatis (spring 4.1.3, mybatis 3.2.8 и mybatis-spring 1.2.2), который для этого сканирует (xml) файлы отображения.
Интерфейсы репозитория (DAO) автоматически подключаются к вызывающим их сервисным классам, например

@Autowired  
private UserRepositoryInterface repository;  

Интерфейсы репозитория помечены @Repository
У меня есть PersistenceConfigurer с аннотациями @Configuration и @MapperScan, который содержит два @Bean метода:

  • Источник данных Источник данных ()
  • SqlSessionFactoryBean sqlSessionFactory (Источник данных Источник данных)

DataSource и sqlSessionFactory не вызываются до конца процесса запуска, что, кажется, является проблемой.
Я попытался изменить это, добавив @Order(0) в PersistenceConfigurer, но это не помогло. Перемещение двух Bean-компонентов в другие классы Configuration также не имело положительного эффекта.
Для Spring я использую конфигурацию Java, без xml.
В ответ на комментарии вот весь PersistenceConfigurer:

package org.xx.xxxxxxx.configuration;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jndi.JndiTemplate;

import javax.naming.NamingException;
import javax.sql.DataSource;

/**
 * This class configures the application's persistence layer.
 */
@Configuration
@MapperScan(basePackages = "org.xx.xxxxxxx.repository")
public class PersistenceConfigurer {
    static Logger LOGGER = LogManager.getLogger(PersistenceConfigurer.class);
    @Value("${jdbc.datasource}")
    private String jdbcDatasource;   // in jdbc.properties: jdbc.datasource=jdbc/OurDS

@Value("classpath*:sqlmapper/*.xml")
private Resource[] mapperFiles;

@Value("classpath:mybatisConfig.xml")
private Resource myBatisConfig;

/**
 * @return The configured data source.
 */
@Bean
public DataSource dataSource() {
    JndiTemplate jndiTemplate = new JndiTemplate();
    DataSource dataSource = null;
    LOGGER.debug("Configuring datasource creating datasource with jndiname " + jdbcDatasource);
    try {
        // this works for weblogic,  but not for Tomcat
        dataSource = (DataSource) jndiTemplate.lookup(jdbcDatasource);
        LOGGER.debug("Configuring datasource successfully created datasource " + dataSource);
    } catch (NamingException e) {
        LOGGER.error("Configuring datasource error creating datasource NamingException " + jdbcDatasource);

    } catch (Exception e) {
        LOGGER.error("Configuring datasource error creating datasource " + jdbcDatasource);
        e.printStackTrace();
    }
    return dataSource;
}

/**
 * @param dataSource A configured data source.
 * @return The SQL session factory bean for data management.
 */
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {
    LOGGER.debug("sqlSessionFactory making SqlSessionFactoryBean with datasource " + dataSource);
    SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
    factoryBean.setDataSource(dataSource);
    factoryBean.setMapperLocations(mapperFiles);
    factoryBean.setConfigLocation(myBatisConfig);
    return factoryBean;
    }
}

person JvdLinden    schedule 24.03.2015    source источник
comment
Как вы создаете поиск JNDI источника данных или локально создаете пул соединений?   -  person Karthik Prasad    schedule 25.03.2015
comment
Поиск JNDI. Приложение может быть развернуто для разных владельцев. Администратор сервера weblogic устанавливает файлы источников данных и войны.   -  person JvdLinden    schedule 25.03.2015
comment
хм ...... Тогда в этом и проблема, стоит один раз посмотреть конфигурационный файл spring. Можете ли вы опубликовать свой файл конфигурации и имя JNDI weblogic. У меня была аналогичная проблема ....... это была пропущенная конфигурация JNDI   -  person Karthik Prasad    schedule 25.03.2015
comment
Если вы имеете в виду файл конфигурации Spring: мы используем только конфигурацию Java. Или вы имеете в виду файл-источник данных? В PersistenceConfigurer есть: @Value ($ {jdbc.datasource}) private String jdbcDatasource; // в jdbc.properties: jdbc.datasource = jdbc / OurDS. Кажется, все в порядке, без NamingException или другого исключения.   -  person JvdLinden    schedule 25.03.2015
comment
Да Конфигурация Java   -  person Karthik Prasad    schedule 25.03.2015
comment
Я добавил код PersistenceConfigurer выше   -  person JvdLinden    schedule 26.03.2015
comment
Для полноты: я временно изменил код PersistenceConfigurer: нет JNDI lookup / datasourcefile, но я получаю такие данные, как идентификатор пользователя и пароль, из файла jdbc.properties. Эффект такой же.   -  person JvdLinden    schedule 26.03.2015
comment
Я не использую MyBatis, но похоже, что вы добавили данные картографа дважды (один раз с @MapperScan и один раз с factoryBean.setMapperLocations(mapperFiles). Это проблема?   -  person Dave Syer    schedule 26.03.2015
comment
Нет, необходимы две конфигурации: одна указывает на классы Java RepositorInterface, а другая - на запросы в файлах сопоставления. Удаление первого делает развертывание невозможным, удаление второго ускоряет развертывание, но приводит к ошибкам выполнения: запросы не обнаруживаются / не выполняются.   -  person JvdLinden    schedule 26.03.2015
comment
где вы импортируете источник свойств (файл свойств), импортируете ли вы его другой класс конфигурации?   -  person Karthik Prasad    schedule 26.03.2015
comment
application.properties (только элемент applicationPath), jdbc.properties и 2 message.properties. Все это упоминается в @Configuration аннотированном WebMvcConfigurerAdapter, файлах сообщений в @Bean аннотированном MessageSource, двух других в его @Bean аннотированном PropertySourcesPlaceholderConfigurer.   -  person JvdLinden    schedule 26.03.2015
comment
Я считаю, что вы можете попробовать ввести свойства в PersistenceConfigurer напрямую, поскольку webMvc является дочерним контекстом контекста приложения. PersistenceConfigurer может не получить эти свойства   -  person Karthik Prasad    schedule 29.03.2015
comment
Мы попробовали жестко закодировать свойства в PersistenceConfigurer. Это не подействовало.   -  person JvdLinden    schedule 31.03.2015
comment
Но это возымело действие, когда мы также изменили SqlSessionFactoryBean на SqlSessionFactory. Это работало только в сочетании с жестким кодированием свойств. Мы также пытаемся обойти это, пытаясь создать PropertySourcesPlaceholderConfigurer раньше. Продолжение следует...   -  person JvdLinden    schedule 31.03.2015


Ответы (1)


Мой коллега нашел главное решение: не возвращать SqlSessionFactoryBean, а SqlSessionFactory.
До этого решения время запуска зависело от количества RepositoryInterfaces:
5 RepositoryInterfaces: 12 секунд, 6:> 80 секунд; 7: 9 минут заканчиваются проблемами с памятью.
После этого всегда 9 секунд.

Это решение сработало не сразу, потому что благодаря исправлению теперь создание происходит так рано, что оно предшествует созданию PropertySourcesPlaceholderConfigurer, объявленному в WebMvcConfigurerAdapter. Итак, мы помещаем разрешение необходимых свойств непосредственно в PersistenceConfigurer. Спасибо, Картик за это предложение.

Измененный код в PersistenceConfigurer: добавлен импорт:
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

3 измененных частных переменных (теперь все 3 - простые строки без аннотации @Value):

private String jdbcDatasource = "jdbc/OurDS";  // moved away from jdbc.properties (was only property left there)

private String mapperFilesLocation = "classpath*:sqlmapper/*.xml";

private String myBatisConfigLocation = "classpath:mybatisConfig.xml";

Один измененный метод, основное изменение - возвращаемый объект. Добавлены три строки для разрешения свойств.

/**
 * @param dataSource A configured data source.
 * @return The SQL session factory (org.apache.ibatis.session.defaults.DefaultSqlSessionFactory).
 * @throws Exception on sqlSessionFactoryBean.getObject(), IOException on resolver.getResources 
 */
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) {
    LOGGER.debug("sqlSessionFactory making SqlSessionFactoryBean with datasource " + dataSource);
    SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
    factoryBean.setDataSource(dataSource);
    PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    Resource[] mapperFiles = resolver.getResources(mapperFilesLocation);
    Resource myBatisConfig = resolver.getResource(myBatisConfigLocation);   
    factoryBean.setMapperLocations(mapperFiles);
    factoryBean.setConfigLocation(myBatisConfig);
    return factoryBean.getObject();
} 
person JvdLinden    schedule 03.04.2015