最近在将之前遗留的一个数据服务项目从SSH移植到SpringBoot下,进行拆分作为单独的微服务进行运行。而在移植完成运行项目时,出现莫名异常,异常输出如下:
Description:
Field xxxxxxx_Repository in cn.cupid.service.impl.xxxxxxx_Service_Impl required a bean named 'mongoTemplate' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean named 'mongoTemplate' in your configuration.
很明显,报的异常时是没有为其中一个Service的实现类注入mongoTemplate。于是考虑是否是自己代码中疏忽了,经过反复检查代码无问题。进而这种异常是否只有这个Service会出现呢?将这个Service有关的类注释之后,进行测试这个异常仍然存在。这个时候就可以确定了,是整个项目中的mongoTemplate注入失败。回顾代码,mongoTemplate确实已经被自己手动注入过,而且在之前的项目中是证实注入mongoTempate是成功的。我采用的注入方式是在SpringBoot项目入口类进行注入,注入代码如下:
package cn.cupid;
import com.mongodb.MongoClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.client.RestTemplate;
@ComponentScan(basePackages = {"cn.cupid.*"})
@EnableDiscoveryClient
@EnableScheduling
@EnableCircuitBreaker
@EnableMongoRepositories
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
public MongoClient mongo() throws Exception {
return new MongoClient("localhost", 27017);
}
//注入mongoTemplate
@Bean
public MongoTemplate getMongoTemplate() throws Exception{
return new MongoTemplate(mongo(), databaseName);
}
}
经过查阅资料进行反复测试,终于找到解放方法,注入mongoTemplate方式如下:
package cn.cupid.config;
import com.mongodb.MongoClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;
/**
* @Author: cupid
* Created by Cupid520 on 2019/1/16.
* @Description:
*/
@Configuration
public class MongoConfig {
@Bean
public MongoClient mongoClient() {
return new MongoClient("localhost", 27017);
}
@Bean
public MongoTemplate mongoTemplate() {
return new MongoTemplate(mongoClient(), "newdb");
}
}
采用@Configuration注解方式,新建类进行注入,项目运行成功。
同样是注入,为什么后一种可以成功呢?按Spring加载Bean进行管理进行猜想,应该是前一种方式的mongoTemplate注入在Service类之后,所以导致项目运行失败。验证如下:
2019-01-16 21:44:07.442 INFO 9432 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
-------------DemoApplication init--------
---------MongoConfig------
2019-01-16 21:44:08.149 INFO 9432 --- [ restartedMain] org.mongodb.driver.cluster : Cluster created with settings {hosts=[localhost:27017], mode=SINGLE, requiredClusterType=UNKNOWN, serverSelectionTimeout='30000 ms', maxWaitQueueSize=500}
2019-01-16 21:44:08.277 INFO 9432 --- [localhost:27017] org.mongodb.driver.connection : Opened connection [connectionId{localValue:1, serverValue:11}] to localhost:27017
2019-01-16 21:44:08.282 INFO 9432 --- [localhost:27017] org.mongodb.driver.cluster : Monitor thread successfully connected to server with description ServerDescription{address=localhost:27017, type=STANDALONE, state=CONNECTED, ok=true, version=ServerVersion{versionList=[2, 6, 9]}, minWireVersion=0, maxWireVersion=2, maxDocumentSize=16777216, logicalSessionTimeoutMinutes=null, roundTripTimeNanos=2441051}
---------xxxxxxxxxxxx_Impl init---------
-------------getMongoTemplate init--------
2019-01-16 21:44:09.835 WARN 9432 --- [ restartedMain] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources.
2019-01-16 21:44:09.835 INFO 9432 --- [ restartedMain] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.
2019-01-16 21:44:09.846 WARN 9432 --- [ restartedMain] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources.
很明显,猜想正确,顺利出坑。