我有
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
如何解决错误?
该bean不是由Spring创建的,因为componentScanattribute错过了所在的包ProductServiceImpl。
componentScan
ProductServiceImpl
此外,@EnableJpaRepositories失踪。因此,Spring无法连接您的存储库。
@EnableJpaRepositories
@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类所属的父包中或属于它的子包,则不再需要指定这两个注释:
Application
@ComponentScan(basePackages = {"hello","com.ensat.controllers"}) @EntityScan("com.ensat.entities")
在@SpringBootApplication课堂上。
@SpringBootApplication
例如,移入Application该 com.ensat软件包并将所有Bean移入该软件包或其中一个子软件包都将解决您的配置问题并减轻您的配置。
com.ensat
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 /实体/存储库等。
basePackage
文档参考了这一点。
在这里:
许多Spring Boot开发人员的主类始终带有@ Configuration,@ EnableAutoConfiguration和@ComponentScan注释。由于这些注释经常一起使用(特别是如果您遵循上述最佳实践),因此Spring Boot提供了一种方便的@SpringBootApplication替代方法。 @SpringBootApplication注释等效于使用@ Configuration,@ EnableAutoConfiguration和@ComponentScan及其默认属性
许多Spring Boot开发人员的主类始终带有@ Configuration,@ EnableAutoConfiguration和@ComponentScan注释。由于这些注释经常一起使用(特别是如果您遵循上述最佳实践),因此Spring Boot提供了一种方便的@SpringBootApplication替代方法。
@SpringBootApplication注释等效于使用@ Configuration,@ EnableAutoConfiguration和@ComponentScan及其默认属性
这里讨论了@EnableAutoConfiguration 77.3 Use Spring Data Repository point提供的关于实体发现的内容 :
@EnableAutoConfiguration
Spring Boot会根据发现的@EnableAutoConfiguration尝试猜测@Repository定义的位置。 要获得更多控制权,请使用@EnableJpaRepositories批注(来自Spring Data JPA)。