我堆叠了上面提到的异常,并且实际上并没有低估它出现的原因。我正在使用spring boot并通过注释声明bean。
应用程序由此类执行:
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
我的问题bean有以下声明:
@Service
public class OrderSvc extends AbstractService implements DAOService {
我尝试将它放在以下bean中:
@RestController
public class OrderController {
@Autowired
CarSvc carSvc;
@Autowired
OrderSvc orderSvc;
并出现例外:Could not autowire field: biz.Services.OrderSvc biz.controllers.rest.administrator.OrderController.orderSvc; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [biz.Services.OrderSvc] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
我还有CarSvc
bean,它位于与OrderSvc
相同的包中,并扩展了相同的类,但注入没有问题
@Service
public class CarSvc extends AbstractService implements DAOService<Car> {
您对此异常出现的原因有何看法?
答案 0 :(得分:2)
Spring为声明@Transactional的类创建代理,以便它能够向对象添加事务行为和截获的调用。如果bean扩展了任何接口,Spring将使用JDK Reflection API创建动态代理,这只能通过接口来完成。代理是实现相同接口的新对象。所以你的目标bean不是你的实现,而是代理。这就是为什么你得到一个非限定bean的例外。
另一方面,CGLIB可以通过子类化来创建代理。因此,要使其正常工作,您需要将bean类型更改为接口,或者可以使用@EnableTransactionManagement(proxyTargetClass = true)配置cglib。
答案 1 :(得分:1)
尝试使用接口而不是实现来自动装配bean:
@RestController
public class OrderController {
@Autowired
@Qualifier("carSvc")
DAOService carSvc;
@Autowired
@Qualifier("orderSvc")
DAOService orderSvc;
}
编辑:但在此之前,您必须为您的服务命名:
@Service("carSvc")
public class CarSvc extends AbstractService implements DAOService<Car> {}
@Service("orderSvc")
public class OrderSvc extends AbstractService implements DAOService<Order> {}
这里发生的是Spring根据CarSvc,OrderSvc生成服务的代理并实现DAOService,但不扩展CarSvc,OrderSvc。
//somthing like this
class CarSvcProxy implement DAOService {
public Object getOrder(Long id) {
try {
// ...
txManager.commit();
} catch (Exception ex) {
txManager.rollback();
}
}
}
@RestController
public class OrderController {
//So when you do this :
@Autowired
CarSvc carSvc;
//it's somehow like if you did :
CarSvc carSvc = new CarSvcProxy(); //carSvc != CarSvcProxy
//But this will work :
DAOService carSvc = new CarSvcProxy(); //because CarSvcProxy implement DAOService
}
答案 2 :(得分:0)
我找到了导致异常的代码,但我真的不明白为什么。
在我的OrderSvc
中,有以下方法:
@Transactional(readOnly = true)
public Object getOrder(Long id) {
final Order order = getDAO().findOne(id);
OrderDTO orderDTO = modelMapper.map(order, OrderDTO.class);
return orderDTO;
}
因此,如果注释@Transactional(readOnly = true)
被排除在外,那么应用程序可以毫无问题地完成...您是否有任何想法为什么这个注释会导致NoSuchBeanDefinitionException
?