在启动过程中,Spring警告日志会显示有关创建例如
“名称为'userRepositoryInterface'的bean ...初始化方法的调用失败;嵌套异常为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
注释我有一个
@Configuration
和@MapperScan
注释的PersistenceConfigurer,其中包含两个@Bean
方法:数据源dataSource()
SqlSessionFactoryBean sqlSessionFactory(DataSource数据源)
直到启动过程结束,才调用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;
}
}
最佳答案
我的一位同事找到了主要解决方案:不是返回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个都是简单的String,没有@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();
}