springboot 启动报错:required a bean of type 'xxxRepository' that could not be found

springboot启动的时候报错,错误如下:

Field demoRepository in com.ge.serviceImpl.DemoServiceImpl required a bean of type 'com.ge.dao.DemoRepository' that could not be found.

The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)

Action:

Consider defining a bean of type 'com.ge.dao.DemoRepository' in your configuration.

原因分析:

由于搭建的springboot项目是分模块搭建的,使用的是spring-data-jpa

com.ge.dao.DemoRepository是在ge-springboot-dao模块下。代码如下

public interface DemoRepository extends JpaRepository<Demo, Integer> {}

但是SpringBootApplication是在ge-springboot-web这个module下。

com.ge.MainApplication

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class MainApplication {
  public static void main(String[] args) {
    SpringApplication.run(MainApplication.class, args);
  }
}

看错误信息的意思是spring找不到这个bean,也就是扫描不到。

尝试的方法:

1. 在 DemoRepository 加注解@Repository,然而好像并没有什么卵用,还是同样的错误。

2. 手动添加一个jpa相关的configuration类,同样没什么卵用。。

参考:https://stackoverflow.com/questions/46315919/spring-boot-2-0-0-m4-required-a-bean-named-entitymanagerfactory-that-could-not

 1 @Configuration
 2 @ComponentScan(basePackages = "com.ge")
 3 @EnableJpaRepositories(
 4     basePackages = "com.ge",
 5     entityManagerFactoryRef = "entityManagerFactory",
 6     transactionManagerRef = "transactionManager")
 7 @EnableTransactionManagement
 8 public class DaoConfiguration {
 9 
10   @Autowired private Environment environment;
11 
12   @Value("${datasource.sampleapp.maxPoolSize:10}")
13   private int maxPoolSize;
14 
15   /*
16    * Populate SpringBoot DataSourceProperties object directly from
17   application.yml
18    * based on prefix.Thanks to .yml, Hierachical data is mapped out of
19   the box with matching-name
20    * properties of DataSourceProperties object].
21    */
22   @Bean
23   @Primary
24   @ConfigurationProperties(prefix = "spring.datasource")
25   public DataSourceProperties dataSourceProperties() {
26     return new DataSourceProperties();
27   }
28 
29   /*
30    * Configure HikariCP pooled DataSource.
31    */
32   @Bean
33   public DataSource dataSource() {
34     DataSourceProperties dataSourceProperties = dataSourceProperties();
35     HikariDataSource dataSource =
36         (HikariDataSource)
37             org.springframework.boot.jdbc.DataSourceBuilder.create(
38                     dataSourceProperties.getClassLoader())
39                 .driverClassName(dataSourceProperties.getDriverClassName())
40                 .url(dataSourceProperties.getUrl())
41                 .username(dataSourceProperties.getUsername())
42                 .password(dataSourceProperties.getPassword())
43                 .type(HikariDataSource.class)
44                 .build();
45     dataSource.setMaximumPoolSize(maxPoolSize);
46     return dataSource;
47   }
48 
49   /*
50    * Entity Manager Factory setup.
51    */
52   @Bean
53   public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws NamingException {
54     LocalContainerEntityManagerFactoryBean factoryBean =
55         new LocalContainerEntityManagerFactoryBean();
56     factoryBean.setDataSource(dataSource());
57     factoryBean.setPackagesToScan(new String[] {"webroot.websrv"});
58     factoryBean.setJpaVendorAdapter(jpaVendorAdapter());
59     factoryBean.setJpaProperties(jpaProperties());
60     return factoryBean;
61   }
62 
63   /*
64    * Provider specific adapter.
65    */
66   @Bean
67   public JpaVendorAdapter jpaVendorAdapter() {
68     HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
69     return hibernateJpaVendorAdapter;
70   }
71 
72   /*
73    * Here you can specify any provider specific properties.
74    */
75   private Properties jpaProperties() {
76     Properties properties = new Properties();
77     properties.put(
78         "hibernate.dialect",
79         environment.getRequiredProperty("spring.jpa.properties.hibernate.dialect"));
80     return properties;
81   }
82 
83   @Bean
84   @Autowired
85   public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
86     JpaTransactionManager txManager = new JpaTransactionManager();
87     txManager.setEntityManagerFactory(emf);
88     return txManager;
89   }
90 }

 

3. 把主启动类MainRepository上的exclude= {DataSourceAutoConfiguration.class} 去掉,然后就可以了。

原来为什么加这个参数?因为没有在application.yml或者application.properties中配置spring.datasource.url这个属性,所以启动会报错。

但是后来我配置了数据源相关的属性,应该把exclude= {DataSourceAutoConfiguration.class}去掉,而且spring-data-jpa是操作数据库相关的框架,可能exculde数据源配置导致spring不会自动扫描repository。

 

总结:

这是我出现@autowired失败的原因。可能对别人并不适用。

但是对于springboot多模块project来说,能够@autowired自动注入的前提的,我举个例子来说明

我这里有3个模块:

ge-springboot-dao 模块中有 DemoRepositry

package com.ge.repository;

public
interface DemoRepository extends JpaRepository<Demo, Integer> {}

ge-springboot-service 模块中有 DemoServiceImpl

package com.ge.service.impl;

@Service
public class DemoServiceImpl implements DemoService { @Autowired private DemoRepository demoRepository; @Override public Demo save(Demo demo) { return demoRepository.save(demo); } @Override public Demo get(Integer id) { return demoRepository.getOne(id); } }

ge-springboot-web 模块中有DemoController 和SpringBootApplication

package com.ge.controller;

@Controller @RequestMapping(
"/demo") public class DemoController { @Autowired private DemoService demoService; @ResponseBody @GetMapping("/save") public Demo save() { Demo demo = new Demo(); demo.setName("gejunling"); return demoService.save(demo); } }

web模块能自动注入service模块的bean,service模块能自动注入dao模块的bean,前提就是所有的这些bean所在的java类都要在同一个package下。

可以发现,我这3个bean虽然在不同的module下,但是所在的packge都是在 com.ge.xxx.xxx

然后在@SpringBootApplication添加scanBasePackge="com.ge"即可。如下

@SpringBootApplication(scanBasePackages = {"com.ge"})
public class MainApplication {
  public static void main(String[] args) {
    SpringApplication.run(MainApplication.class, args);
  }
}

当然,如果不使用scanBasePackge="com.ge"来指指定扫描的packge也可以,但是要保证springboot主启动类要在所有bean的同级或者上级packge。

比如我的MainApplication就是com.ge这个包下。

 

如果有不同的package需要spring自动扫描,同样可以使用scanBasePackge={"com.ge1","com.ge2","com.ge3"}

 

posted @ 2018-12-16 19:29  gejunling  阅读(...)  评论(...编辑  收藏