【问题标题】:springboot autowiring @Repository inside of @Configuration not working@Configuration内部的springboot自动装配@Repository不起作用
【发布时间】:2016-08-03 11:48:05
【问题描述】:

我有一个简单的 Spring Boot 应用程序,其中我有一个 jpa 存储库对象,我想在 @Configuration 类中自动装配,如下所示。

@Configuration
public class Appconfig {

    @Bean
    @Autowired
    public  PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(OctopusPropertiesRepository repo) {
        PropertySourcesPlaceholderConfigurer property = new PropertySourcesPlaceholderConfigurer();
        Map<String,Object> props = new ConcurrentHashMap<>();
        List<OctopusProperties> loadedSettings = repo.findAll();
        loadedSettings.forEach(entry -> props.put(entry.getKey(), entry.getValue()));
        MutablePropertySources mutablePropertySources = new MutablePropertySources();
        mutablePropertySources.addFirst(new MapPropertySource("custom", props));
        property.setPropertySources(mutablePropertySources);
        return property;
    }
}

这是@Repository

@Repository
public interface OctopusPropertiesRepository extends JpaRepository<OctopusProperties, Long> {
}

我得到以下异常。

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.app.OctopusPropertiesRepository]

如果我没有成功地进行配置和启动应用程序,我会从执行器中看到 bean 可用。这里有什么问题?为什么我不能在@Configuration 内连接@Repository

P.S. 这两个java文件在同一个文件夹下:com.example.app

P.P.S. 我的项目的 Eclipse 视图:

【问题讨论】:

  • 包含扫描组件的类。还请在列表中包含包裹。可能是主要课程?
  • 主类在根包中,其他类在同一个包中。我认为它与时间有点相关,因为如果我不使用这个配置,spring 会生成这个 bean。
  • 如果你添加一个简单的成员,如下所示,在配置类中 Spring 会找到它吗? @Autowired OctopusPropertiesRepository octopusPropertiesRepository
  • 不,我试过了,但没有改变:(
  • @luboskrnac 我已经添加了屏幕截图

标签: java spring spring-boot spring-data-jpa


【解决方案1】:

使用@PostConstruct。

@Autowired PropertySourcesPlaceholderConfigurer property;


@Autowired OctopusPropertiesRepository repo;


   @PostConstruct
    public  void onInit() {

        Map<String,Object> props = new ConcurrentHashMap<>();
        List<OctopusProperties> loadedSettings = repo.findAll();
        loadedSettings.forEach(entry -> props.put(entry.getKey(), entry.getValue()));
        MutablePropertySources mutablePropertySources = new MutablePropertySources();
        mutablePropertySources.addFirst(new MapPropertySource("custom", props));
        property.setPropertySources(mutablePropertySources);

    }

【讨论】:

  • 你不是说@PostConstruct吗?
  • 不知道是需要手动创建PropertySourcesPlaceholderConfigurer Bean实例还是Spring boot自动创建。
【解决方案2】:

根据@Bean javadoc:

BeanFactoryPostProcessor-returning @Bean methods
Special consideration must be taken for @Bean methods that return Spring 
BeanFactoryPostProcessor (BFPP) types. Because BFPP objects must be    
instantiated very early in the container lifecycle, they can interfere with
processing of annotations such as @Autowired, @Value, and @PostConstruct
within @Configuration classes. To avoid these lifecycle issues, mark BFPP
returning @Bean methods as static. For example: 

 @Bean
 public static PropertyPlaceholderConfigurer ppc() {
     // instantiate, configure and return ppc ...
 }


By marking this method as static, it can be invoked without causing 
instantiation of its declaring @Configuration class, thus avoiding the above-
mentioned lifecycle conflicts. Note however that static @Bean methods will not   
be enhanced for scoping and AOP semantics as mentioned above. This works out
in BFPP cases, as they are not typically referenced by other @Bean methods. As
a reminder, a WARN-level log message will be issued for any non-static @Bean
methods having a return type assignable to BeanFactoryPostProcessor.

所以根据这个,你的propertySourcesPlaceholderConfigurer()应该是静态的。

编辑: 抱歉编辑晚了。 我认为您不能在这里使用 Hibernate 存储库,因为 BeanFactoryPostProcessor 在 hibernate 和 jpa 所需的任何依赖项之前被实例化。 也许你可以在这里使用 JdbcTemplate,至少这对我有用:

@Configuration
public class Appconfig {

    @Bean
    public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        PropertySourcesPlaceholderConfigurer property = new PropertySourcesPlaceholderConfigurer();
        Map<String, Object> props = new ConcurrentHashMap<>();
        List<OctopusProperties> loadedSettings = getAll();
        loadedSettings.forEach(entry -> props.put(entry.getKey(), entry.getValue()));
        MutablePropertySources mutablePropertySources = new MutablePropertySources();
        mutablePropertySources.addFirst(new MapPropertySource("custom", props));
        property.setPropertySources(mutablePropertySources);
        return property;
    }

    @Bean
    public static DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/test");
        dataSource.setUsername("root");
        dataSource.setPassword("root");

        return dataSource;
    }

    private List<OctopusProperties> getAll() {
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource());
        List<OctopusProperties> all = jdbcTemplate.query("select id,key_column,value_column from octopus_properties",
                new RowMapper<OctopusProperties>() {
                    @Override
                    public OctopusProperties mapRow(final ResultSet rs, final int rowNum) throws SQLException {
                        OctopusProperties op = new OctopusProperties();
                        op.setId(rs.getLong("id"));
                        op.setKey(rs.getString("key_column"));
                        op.setValue(rs.getString("value_column"));
                        return op;
                    }
                });
        return all;
    }

}

请注意,我在这里使用了 MySQL,因此数据源已相应配置。

【讨论】:

  • 好点,我不知道提到的部分并希望尝试但仍然是同样的错误:(
  • 是的,我也试过了,同样的错误,让我投资一下,我会回复你
【解决方案3】:

this 问题中解决了类似的问题

可以像这样更改AppConfig 类吗?

@Configuration
public class Appconfig {

    @Autowired
    private OctopusPropertiesRepository repo;

    @Bean
    public  PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        PropertySourcesPlaceholderConfigurer property = new PropertySourcesPlaceholderConfigurer();
        Map<String,Object> props = new ConcurrentHashMap<>();
        List<OctopusProperties> loadedSettings = repo.findAll();
        loadedSettings.forEach(entry -> props.put(entry.getKey(), entry.getValue()));
        MutablePropertySources mutablePropertySources = new MutablePropertySources();
        mutablePropertySources.addFirst(new MapPropertySource("custom", props));
        property.setPropertySources(mutablePropertySources);
        return property;
    }
}

如果此解决方案有效,请恢复。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-03
    • 2013-07-14
    • 1970-01-01
    • 1970-01-01
    • 2017-05-31
    • 1970-01-01
    • 2014-01-03
    相关资源
    最近更新 更多