我是Spring新手,我们正在使用Spring Batch来处理作业 我在下面发布我的全部代码,请分享您的知识: -
这是带有SpringBatchAdmin的Main类文件名: -
@Configuration
@EnableAutoConfiguration(exclude = { BatchAutoConfiguration.class, DataSourceAutoConfiguration.class,
WebMvcAutoConfiguration.class })
//@Import(MainV1Configuration.class)
@ContextConfiguration(classes = { BatchConfiguration.class })
@Import(value={MainV2Configuration.class, FTPConfiguration.class})
public class SpringBatchAdmin extends SpringBootServletInitializer
public static void main(String[] args) {
SpringApplication.run(SpringBatchAdmin.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SpringBatchAdmin.class);
}
}
MainV2Configuration文件
import java.io.File;import javax.sql.DataSource;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.annotation.Scope;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.integration.file.remote.session.SessionFactory;
import org.springframework.integration.ftp.session.DefaultFtpSessionFactory;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
@Configuration
@ImportResource(
value = {
"classpath:org/springframework/batch/admin/web/resources/servlet-config.xml",
"classpath:org/springframework/batch/admin/web/resources/webapp-config.xml"
}
)
public class MainV2Configuration {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
Resource[] resources = {
new ClassPathResource("batch-hsql.properties"),
new ClassPathResource("customercare-job.properties")
};
PropertySourcesPlaceholderConfigurer bean = new PropertySourcesPlaceholderConfigurer();
bean.setLocations(resources);
return bean;
}
}
BatchConfiguration文件: -
package ccp.batch.config;
import java.io.File;import java.util.Arrays;import java.util.List;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.JobOperator;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.launch.support.SimpleJobOperator;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.annotation.Scope;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.integration.file.remote.session.SessionFactory;
import org.springframework.integration.ftp.session.DefaultFtpSessionFactory;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import com.batch.tasklet.FtpGetRemoteFilesTasklet;
@Configuration
@EnableBatchProcessing(modular = true)
public class BatchConfiguration {
@Value("${batch.jdbc.driver}")
private String driverClassName;
@Value("${batch.jdbc.url}")
private String driverUrl;
@Value("${batch.jdbc.user}")
private String driverUsername;
@Value("${batch.jdbc.password}")
private String driverPassword;
@Autowired
@Qualifier("jobRepository")
private JobRepository jobRepository;
@Autowired
private JobLauncher jobLauncher;
@Autowired
private Job job;
@Autowired
JobExplorer jobExplorer;
@Autowired
JobRegistry jobRegistry;
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Bean
public Job job() {
return jobBuilderFactory.get("job").start(step()).build();
}
@Bean
public Step step() {
return stepBuilderFactory.get("step").chunk(1).reader(reader()).writer(writer()).build();
}
@Bean
public ItemReader<String> reader() {
return new ListItemReader<String>(Arrays.asList("1", "2", "3"));
}
@Bean
public ItemWriter<? super Object> writer() {
return new ItemWriter<Object>() {
@Override
public void write(List<? extends Object> items) throws Exception {
System.out.println(items);
}
};
}
@Bean
public JobOperator jobOperator() {
SimpleJobOperator jobOperator = new SimpleJobOperator();
jobOperator.setJobExplorer(jobExplorer);
jobOperator.setJobLauncher(jobLauncher);
jobOperator.setJobRegistry(jobRegistry);
jobOperator.setJobRepository(jobRepository);
return jobOperator;
}
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(driverUrl);
dataSource.setUsername(driverUsername);
dataSource.setPassword(driverPassword);
return dataSource;
}
@Bean
public SimpleJobLauncher jobLauncher() {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository);
return jobLauncher;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
FTP配置文件
package ccp.batch.config;
import java.io.File;import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.integration.file.remote.session.SessionFactory;
import org.springframework.integration.ftp.session.DefaultFtpSessionFactory;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import ccp.batch.tasklet.FtpGetRemoteFilesTasklet;
@Configuration
public class FTPConfiguration {
@Value("${batch.jdbc.driver}")
private String driverClassName;
@Value("${batch.jdbc.url}")
private String driverUrl;
@Value("${batch.jdbc.user}")
private String driverUsername;
@Value("${batch.jdbc.password}")
private String driverPassword;
@Autowired
@Qualifier("jobRepository")
private JobRepository jobRepository;
@Autowired
@Qualifier("myFtpSessionFactory")
private SessionFactory myFtpSessionFactory;
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(driverUrl);
dataSource.setUsername(driverUsername);
dataSource.setPassword(driverPassword);
return dataSource;
}
@Bean
@Scope(value="step")
public FtpGetRemoteFilesTasklet myFtpGetRemoteFilesTasklet()
{
FtpGetRemoteFilesTasklet ftpTasklet = new FtpGetRemoteFilesTasklet();
ftpTasklet.setRetryIfNotFound(true);
ftpTasklet.setDownloadFileAttempts(3);
ftpTasklet.setRetryIntervalMilliseconds(10000);
ftpTasklet.setFileNamePattern("README");
//ftpTasklet.setFileNamePattern("TestFile");
ftpTasklet.setRemoteDirectory("/");
ftpTasklet.setLocalDirectory(new File(System.getProperty("java.io.tmpdir")));
ftpTasklet.setSessionFactory(myFtpSessionFactory);
return ftpTasklet;
}
@Bean
public SessionFactory myFtpSessionFactory()
{
DefaultFtpSessionFactory ftpSessionFactory = new DefaultFtpSessionFactory();
ftpSessionFactory.setHost("ftp.gnu.org");
ftpSessionFactory.setClientMode(0);
ftpSessionFactory.setFileType(0);
ftpSessionFactory.setPort(21);
ftpSessionFactory.setUsername("anonymous");
ftpSessionFactory.setPassword("anonymous");
return ftpSessionFactory;
}
@Bean
public SimpleJobLauncher jobLauncher() {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository);
return jobLauncher;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
FtpGetRemoteFilesTasklet文件
package ccp.batch.tasklet;
import java.io.File;import java.io.FileNotFoundException;
import java.util.List;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.integration.file.filters.SimplePatternFileListFilter;
import org.springframework.integration.file.remote.session.SessionFactory;
import org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer;
import org.springframework.integration.ftp.filters.FtpSimplePatternFileListFilter;
import org.springframework.integration.ftp.inbound.FtpInboundFileSynchronizer;
import org.springframework.integration.sftp.filters.SftpSimplePatternFileListFilter;
import org.springframework.integration.sftp.inbound.SftpInboundFileSynchronizer;
import org.springframework.integration.sftp.session.DefaultSftpSessionFactory;
import org.springframework.util.Assert;
public class FtpGetRemoteFilesTasklet implements Tasklet, InitializingBean
{
private Logger logger = LoggerFactory.getLogger(FtpGetRemoteFilesTasklet.class);
private File localDirectory;
private AbstractInboundFileSynchronizer<?> ftpInboundFileSynchronizer;
private SessionFactory sessionFactory;
private boolean autoCreateLocalDirectory = true;
private boolean deleteLocalFiles = true;
private String fileNamePattern;
private String remoteDirectory;
private int downloadFileAttempts = 12;
private long retryIntervalMilliseconds = 300000;
private boolean retryIfNotFound = false;
public void afterPropertiesSet() throws Exception
{
Assert.notNull(sessionFactory, "sessionFactory attribute cannot be null");
Assert.notNull(localDirectory, "localDirectory attribute cannot be null");
Assert.notNull(remoteDirectory, "remoteDirectory attribute cannot be null");
Assert.notNull(fileNamePattern, "fileNamePattern attribute cannot be null");
setupFileSynchronizer();
if (!this.localDirectory.exists()) {
if (this.autoCreateLocalDirectory) {
if (logger.isDebugEnabled()) {
logger.debug("The '" + this.localDirectory + "' directory doesn't exist; Will create.");
}
this.localDirectory.mkdirs();
}
else {
throw new FileNotFoundException(this.localDirectory.getName());
}
}
}
private void setupFileSynchronizer()
{
if (isSftp()) {
ftpInboundFileSynchronizer = new SftpInboundFileSynchronizer(sessionFactory);
((SftpInboundFileSynchronizer) ftpInboundFileSynchronizer).setFilter(new SftpSimplePatternFileListFilter(fileNamePattern));
}
else {
ftpInboundFileSynchronizer = new FtpInboundFileSynchronizer(sessionFactory);
((FtpInboundFileSynchronizer) ftpInboundFileSynchronizer).setFilter(new FtpSimplePatternFileListFilter(fileNamePattern));
}
ftpInboundFileSynchronizer.setRemoteDirectory(remoteDirectory);
}
private void deleteLocalFiles()
{
if (deleteLocalFiles) {
SimplePatternFileListFilter filter = new SimplePatternFileListFilter(fileNamePattern);
List<File> matchingFiles = filter.filterFiles(localDirectory.listFiles());
if (CollectionUtils.isNotEmpty(matchingFiles)) {
for (File file : matchingFiles) {
FileUtils.deleteQuietly(file);
}
}
}
}
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception
{
deleteLocalFiles();
ftpInboundFileSynchronizer.synchronizeToLocalDirectory(localDirectory);
if (retryIfNotFound) {
SimplePatternFileListFilter filter = new SimplePatternFileListFilter(fileNamePattern);
int attemptCount = 1;
while (filter.filterFiles(localDirectory.listFiles()).size() == 0 && attemptCount <= downloadFileAttempts) {
logger.info("File(s) matching " + fileNamePattern + " not found on remote site. Attempt " + attemptCount + " out of " + downloadFileAttempts);
Thread.sleep(retryIntervalMilliseconds);
ftpInboundFileSynchronizer.synchronizeToLocalDirectory(localDirectory);
attemptCount++;
}
if (attemptCount >= downloadFileAttempts && filter.filterFiles(localDirectory.listFiles()).size() == 0) {
throw new FileNotFoundException("Could not find remote file(s) matching " + fileNamePattern + " after " + downloadFileAttempts + " attempts.");
}
}
return null;
}
Some getters and setters methods *.*
FirstTasklet文件
package ccp.batch.tasklet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
public class FirstTasklet implements Tasklet {
private String property;
@Override
public RepeatStatus execute(StepContribution arg0, ChunkContext arg1) throws Exception {
System.out.println(property);
return RepeatStatus.FINISHED;
}
public void setProperty(String property) {
this.property = property;
}
}
src / main / resource目录中的两个属性文件
batch-hsql.properties customer-job.properties
我不知道的其他事情: - enter image description here
这是在xml文件中: - First-job.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="">// Deleted here because there is limit of characters when posting a question on stackocerflow
<batch:job id="FirstJob" restartable="true">
<batch:step id="firstStep">
<batch:tasklet ref="firstTasklet" start-limit="1" />
</batch:step>
</batch:job>
<bean id="firstTasklet" class="ccp.batch.tasklet.FirstTasklet">
<property name="property" value="${custom-property}" />
</bean>
<batch:job id="FtpJob">
<batch:step id="step1" >
<batch:tasklet ref="myFtpGetRemoteFilesTasklet" />
</batch:step>
</batch:job>
</beans>
Launch-contect.xml文件: -
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="">// Deleted here because there is limit of characters when posting a question on stackocerflow
<context:property-placeholder location="classpath:batch.properties" />
<context:component-scan base-package="ccp.batch" />
<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="${batch.schema.script}" />
</jdbc:initialize-database>
<batch:job-repository id="jobRepository" />
<import resource="classpath:/META-INF/spring/module-context.xml" />
</beans>
以下是我得到的错误: -
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.batch.admin.web.JobController#0' defined in URL [jar:file:/C:/Users/sandy/.m2/repository/org/springframework/batch/spring-batch-admin-manager/1.3.0.RELEASE/spring-batch-admin-manager-1.3.0.RELEASE.jar!/META-INF/spring/batch/servlet/manager/controller-context.xml]: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.springframework.batch.admin.service.JobService]: : Error creating bean with name 'jobService' defined in URL [jar:file:/C:/Users/sandy/.m2/repository/org/springframework/batch/spring-batch-admin-manager/1.3.0.RELEASE/spring-batch-admin-manager-1.3.0.RELEASE.jar!/META-INF/spring/batch/bootstrap/manager/execution-context.xml]: Cannot resolve reference to bean 'jobRepository' while setting bean property 'jobRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobRepository' defined in URL [jar:file:/C:/Users/sandy/.m2/repository/org/springframework/batch/spring-batch-admin-manager/1.3.0.RELEASE/spring-batch-admin-manager-1.3.0.RELEASE.jar!/META-INF/spring/batch/bootstrap/manager/execution-context.xml]: Invocation of init method failed; nested exception is org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (java.net.ConnectException: Connection refused: connect); nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobService' defined in URL [jar:file:/C:/Users/sandy/.m2/repository/org/springframework/batch/spring-batch-admin-manager/1.3.0.RELEASE/spring-batch-admin-manager-1.3.0.RELEASE.jar!/META-INF/spring/batch/bootstrap/manager/execution-context.xml]: Cannot resolve reference to bean 'jobRepository' while setting bean property 'jobRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobRepository' defined in URL [jar:file:/C:/Users/sandy/.m2/repository/org/springframework/batch/spring-batch-admin-manager/1.3.0.RELEASE/spring-batch-admin-manager-1.3.0.RELEASE.jar!/META-INF/spring/batch/bootstrap/manager/execution-context.xml]: Invocation of init method failed; nested exception is org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (java.net.ConnectException: Connection refused: connect)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:747)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1114)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1017)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
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.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:120)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:952)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:941)
at ccp.batch.SpringBatchAdmin.main(SpringBatchAdmin.java:41)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobService' defined in URL [jar:file:/C:/Users/sandy/.m2/repository/org/springframework/batch/spring-batch-admin-manager/1.3.0.RELEASE/spring-batch-admin-manager-1.3.0.RELEASE.jar!/META-INF/spring/batch/bootstrap/manager/execution-context.xml]: Cannot resolve reference to bean 'jobRepository' while setting bean property 'jobRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobRepository' defined in URL [jar:file:/C:/Users/sandy/.m2/repository/org/springframework/batch/spring-batch-admin-manager/1.3.0.RELEASE/spring-batch-admin-manager-1.3.0.RELEASE.jar!/META-INF/spring/batch/bootstrap/manager/execution-context.xml]: Invocation of init method failed; nested exception is org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (java.net.ConnectException: Connection refused: connect)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:336)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1456)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1197)
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:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1017)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:960)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:811)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:739)
... 18 more