在每个添加的DAO接口上指数增加启动时间(Spring初始化)

时间:2015-03-24 08:17:00

标签: java spring performance mybatis spring-java-config

在启动期间,Spring warn-logging显示创建例如
的错误 “名为'userRepositoryInterface'的bean ... init方法的调用失败;嵌套异常是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)mapper文件来执行此操作。
存储库(DAO)接口在调用它们的服务类中自动装配,例如,

@Autowired  
private UserRepositoryInterface repository;  

存储库接口使用@Repository进行分配 我有一个@Configuration@MapperScan带注释的PersistenceConfigurer,它包含两个@Bean方法:

  • DataSource dataSource()
  • SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource)

在启动过程结束之前,不会调用dataSource和sqlSessionFactory,这似乎是问题所在。
我试图通过向PersistenceConfigurer添加@Order(0)来改变它,但这没有任何效果。将两个Bean移动到其他配置类也没有任何积极影响 对于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;
    }
}

1 个答案:

答案 0 :(得分:1)

我的一位同事找到了主要解决方案:不要返回SqlSessionFactoryBean而是SqlSessionFactory 在此解决方案之前,启动时间取决于RepositoryInterfaces的数量:
5 RepositoryInterfaces:12秒,6:> 80秒; 7:9分钟以记忆问题结束 之后,总是9秒。

此解决方案无法立即生效,因为由于修复,现在创建时间过早,它先于在WebMvcConfigurerAdapter中声明的PropertySourcesPlaceholderConfigurer创建。 所以我们直接在PersistenceConfigurer中解析所需的属性。谢谢你,Karthik提出这个建议。

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();
}