Java 考虑在您的配置中定义一个“com.ensat.services.ProductService”类型的 bean

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40451227/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 22:42:53  来源:igfitidea点击:

Consider defining a bean of type 'com.ensat.services.ProductService' in your configuration

javaspringspring-mvcspring-boot

提问by Do Nhu Vy

I have

我有

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@SpringBootApplication
@ComponentScan(basePackages = {"hello","com.ensat.controllers"})
@EntityScan("com.ensat.entities")
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);
    }

}

ProductController.java

产品控制器.java

package com.ensat.controllers;

import com.ensat.entities.Product;
import com.ensat.services.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Product controller.
 */
@Controller
public class ProductController {

    private ProductService productService;

    @Autowired
    public void setProductService(ProductService productService) {
        this.productService = productService;
    }

    /**
     * List all products.
     *
     * @param model
     * @return
     */
    @RequestMapping(value = "/products", method = RequestMethod.GET)
    public String list(Model model) {
        model.addAttribute("products", productService.listAllProducts());
        System.out.println("Returning rpoducts:");
        return "products";
    }

    /**
     * View a specific product by its id.
     *
     * @param id
     * @param model
     * @return
     */
    @RequestMapping("product/{id}")
    public String showProduct(@PathVariable Integer id, Model model) {
        model.addAttribute("product", productService.getProductById(id));
        return "productshow";
    }

    // Afficher le formulaire de modification du Product
    @RequestMapping("product/edit/{id}")
    public String edit(@PathVariable Integer id, Model model) {
        model.addAttribute("product", productService.getProductById(id));
        return "productform";
    }

    /**
     * New product.
     *
     * @param model
     * @return
     */
    @RequestMapping("product/new")
    public String newProduct(Model model) {
        model.addAttribute("product", new Product());
        return "productform";
    }

    /**
     * Save product to database.
     *
     * @param product
     * @return
     */
    @RequestMapping(value = "product", method = RequestMethod.POST)
    public String saveProduct(Product product) {
        productService.saveProduct(product);
        return "redirect:/product/" + product.getId();
    }

    /**
     * Delete product by its id.
     *
     * @param id
     * @return
     */
    @RequestMapping("product/delete/{id}")
    public String delete(@PathVariable Integer id) {
        productService.deleteProduct(id);
        return "redirect:/products";
    }

}

ProductService.java

产品服务.java

package com.ensat.services;

import com.ensat.entities.Product;

public interface ProductService {

    Iterable<Product> listAllProducts();

    Product getProductById(Integer id);

    Product saveProduct(Product product);

    void deleteProduct(Integer id);

}

ProductServiceImpl.java

ProductServiceImpl.java

package com.ensat.services;

import com.ensat.entities.Product;
import com.ensat.repositories.ProductRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * Product service implement.
 */
@Service
public class ProductServiceImpl implements ProductService {

    private ProductRepository productRepository;

    @Autowired
    public void setProductRepository(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }

    @Override
    public Iterable<Product> listAllProducts() {
        return productRepository.findAll();
    }

    @Override
    public Product getProductById(Integer id) {
        return productRepository.findOne(id);
    }

    @Override
    public Product saveProduct(Product product) {
        return productRepository.save(product);
    }

    @Override
    public void deleteProduct(Integer id) {
        productRepository.delete(id);
    }

}

This is my error:

这是我的错误:

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of method setProductService in com.ensat.controllers.ProductController required a bean of type 'com.ensat.services.ProductService' that could not be found.


Action:

Consider defining a bean of type 'com.ensat.services.ProductService' in your configuration.

I have full log: https://gist.github.com/donhuvy/b918e20eeeb7cbe3c4be4167d066f7fd

我有完整的日志:https: //gist.github.com/donhuvy/b918e20eeeb7cbe3c4be4167d066f7fd

This is my full source code https://github.com/donhuvy/accounting/commit/319bf6bc47997ff996308c890eba81a6fa7f1a93

这是我的完整源代码 https://github.com/donhuvy/accounting/commit/319bf6bc47997ff996308c890eba81a6fa7f1a93

How to fix error?

如何修复错误?

采纳答案by davidxxx

The bean is not created by Spring since componentScanattribute misses the package where ProductServiceImplis located.

bean 不是由 Spring 创建的,因为componentScan属性缺少所在的包ProductServiceImpl

Besides,@EnableJpaRepositoriesis missing. So, Spring cannot wire your repository.

此外,@EnableJpaRepositories失踪了。因此,Spring 无法连接您的存储库。

@SpringBootApplication
@ComponentScan(basePackages = {"hello","com.ensat.controllers"})
@EntityScan("com.ensat.entities")

should be replaced by :

应替换为:

@SpringBootApplication
@ComponentScan(basePackages = {"hello","com.ensat.controllers", "com.ensat.services";
})
@EntityScan("com.ensat.entities")
@EnableJpaRepositories("com.ensat.repositories")


It will solve your problem but this way of doing defeats the convention over configuration advantage of Spring and Spring Boot.

它将解决您的问题,但这种做法违背了 Spring 和 Spring Boot 的配置优势的约定。

If the Applicationbean class was located in a parent package which all other bean classes belongs to or to a sub-package of it, you would not need any longer to specify these two annotations :

如果Applicationbean 类位于所有其他 bean 类所属的父包或它的子包中,您将不再需要指定这两个注释:

@ComponentScan(basePackages = {"hello","com.ensat.controllers"})
@EntityScan("com.ensat.entities")

in the @SpringBootApplicationclass.

@SpringBootApplication课堂上。

For example, moving Applicationin the com.ensatpackage and move all your beans in this package or in a child of it will both solve your configuration issues and alleviate your configuration.

例如,移动Applicationcom.ensat包装和移动在这个包或它的一个孩子所有的豆类都将解决您的配置问题,减轻您的配置。

package com.ensat;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application extends SpringBootServletInitializer {
    ...
}

Why ?

为什么 ?

Because the @SpringBootApplicationincludes already them (and more) :

因为@SpringBootApplication已经包含它们(以及更多):

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
        @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

But that uses the package of the current class as basePackagevalue to discover beans/entities/repositories, etc...

但这使用当前类的包作为basePackage值来发现 bean/实体/存储库等......

The documentation refers this point.

文档提到了这一点。

Here:

在这里

Many Spring Boot developers always have their main class annotated with @Configuration, @EnableAutoConfiguration and @ComponentScan. Since these annotations are so frequently used together (especially if you follow the best practices above), Spring Boot provides a convenient @SpringBootApplication alternative.

The @SpringBootApplication annotation is equivalent to using @Configuration, @EnableAutoConfiguration and @ComponentScan with their default attributes

许多 Spring Boot 开发人员总是用 @Configuration、@EnableAutoConfiguration 和 @ComponentScan 注释他们的主类。由于这些注释经常一起使用(特别是如果您遵循上述最佳实践),Spring Boot 提供了一个方便的 @SpringBootApplication 替代方案。

@SpringBootApplication 注解相当于使用@Configuration、@EnableAutoConfiguration 和@ComponentScan 及其默认属性

Here it discusses about entities discovery provided by @EnableAutoConfiguration77.3 Use Spring Data repositories point:

这里讨论了@EnableAutoConfiguration77.3 Use Spring Data repositories point提供的实体发现 :

Spring Boot tries to guess the location of your @Repository definitions, based on the @EnableAutoConfiguration it finds.To get more control, use the @EnableJpaRepositories annotation (from Spring Data JPA).

Spring Boot 尝试根据它找到的 @EnableAutoConfiguration 猜测 @Repository 定义的位置。要获得更多控制,请使用 @EnableJpaRepositories 注释(来自 Spring Data JPA)。

回答by malvadao

I was experiencing this very error, and it took me a whole afternoon to figure it out. I have checked every stackoverflowpost, spring.iodocs, github issue related to this issue, and none of the answers could solve what was wrong.

我遇到了这个错误,我花了整整一个下午才弄明白。我已经检查了每个stackoverflow帖子、spring.io文档、与此问题相关的 github 问题,但没有一个答案可以解决问题所在。

In summary, I have tried:

总之,我已经尝试过:

  1. Restructuring and renaming my packages and classes
  2. Defining alternate classes for configuration
  3. Deleting or remaking erroneous classes
  4. Annotating my classes as thoroughly as possible
  5. Defining classes altogether
  6. Creating multiple code implementations to @Autowire my repositories
  7. Banging my head on the wall in desperation -- okay, I might have overstepped on this a bit
  1. 重组和重命名我的包和类
  2. 为配置定义替代类
  3. 删除或重新制作错误的类
  4. 尽可能彻底地注释我的课程
  5. 完全定义类
  6. 为@Autowire 我的存储库创建多个代码实现
  7. 绝望地把我的头撞在墙上——好吧,我可能有点过头

Given I had two repositories, none of them was being recognized by @ComponentScanor @EntityScanannotations. So in summary, I could not instantiate or perform any actions with them.

鉴于我有两个存储库,@ ComponentScan@EntityScan注释都无法识别它们。所以总而言之,我无法实例化它们或对它们执行任何操作。

What did the trick for me, and what i'd suggest you do if you have exhausted your attempts is

对我来说有什么诀窍,如果你已经用尽了你的尝试,我建议你做的是

  1. Double-checking the project dependencies in pom.xml. The error might not be related to your code (as it wasn't on mine).
  2. If your dependencies are correct, then create a new Maven projectwith your revised pom.xml.
  3. Update your Maven dependencies. It might be worth mentioning that I have done so through my IDE, which is the Eclipse + Spring Tool Suite (I don't believe the Spring Tool Suite did much of a difference in updating) 4.Structure your packagesso that they follow the best practices (there's a nice article about this here.)
  4. Then, carefully, migrate your filesback. Start with the beans, execute your program, check for errors; then repositories, execute, test; then any startup scripts; then controllers etc. Take your time and make sure everything works.
  1. 仔细检查 pom.xml 中的项目依赖项。该错误可能与您的代码无关(因为它不在我的身上)。
  2. 如果您的依赖项正确,则使用修改后的pom.xml创建一个新的 Maven 项目
  3. 更新您的 Maven 依赖项。值得一提的是,我是通过我的 IDE 完成的,它是 Eclipse + Spring 工具套件(我认为 Spring 工具套件在更新方面没有太大区别) 4.构建您的包,以便它们遵循最佳实践(有这个一个不错的文章在这里。)
  4. 然后,小心地将您的文件迁移回来。从 bean 开始,执行你的程序,检查错误;然后存储库,执行,测试;然后是任何启动脚本;然后是控制器等。慢慢来,确保一切正常。

Sometimes it can be very painful to debug these applications. I have had my share. I hope it helps!

有时调试这些应用程序会非常痛苦。我有我的份额。我希望它有帮助!