当前位置: 首页 > 知识库问答 >
问题:

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

轩辕华辉
2023-03-14

我有

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

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

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

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);
    }

}

这是我的错误:

***************************
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.

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

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

如何修复错误?

共有1个答案

司空赞
2023-03-14

bean不是由spring创建的,因为componentscan属性丢失了ProductServiceImpl所在的包。

此外,缺少@enablejparepositories。因此,spring无法连接您的存储库。

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

应改为:

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

它将解决您的问题,但这种做法击败了spring和spring boot的配置优势。

如果applicationbean类位于所有其他bean类所属的父包或其子包中,则不再需要指定以下两个注释:

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

@SpringBootApplication类中。

例如,在com.ensat包中移动application并在此包或其子包中移动所有bean,既可以解决配置问题,又可以减轻配置。

package com.ensat;

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

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

为什么?

因为@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 {

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

文档中提到了这一点。

这里:

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

@SpringBootApplication注释等同于使用@Configuration、@EnableAutoConfiguration和@ComponentScan及其默认属性

这里讨论了@EnableAutoConfiguration77.3提供的实体发现使用spring数据存储库点:

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

 类似资料: