NoSuchBeanDefinitionException:没有

时间:2017-02-14 00:41:03

标签: java spring spring-boot dependency-injection

我堆叠了上面提到的异常,并且实际上并没有低估它出现的原因。我正在使用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> {

您对此异常出现的原因有何看法?

3 个答案:

答案 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