2016-08-03 3 views
3

У меня есть простое приложение загрузки весны, в котором у меня есть объект репозитория jpa, который я хочу сделать autowire внутри класса @Configuration, как показано ниже.springboot autowiring @Repository внутри @ Конфигурация не работает

@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 доступен. В чем проблема? почему я не могу подключить @Repository внутри @Configuration.

P.S. Эти два файла java находятся в одной папке: com.example.app

P.P.S. Eclipse, вид моего проекта:

enter image description here

+1

Включает класс, который сканирует компоненты. Пожалуйста, также включите пакеты в списки. Вероятно, основной класс? – luboskrnac

+0

Основной класс находится в корневом пакете и все остальные классы в одном пакете. Я думаю, что это несколько связано с временем, потому что весна генерирует этот компонент, если я не использую эту конфигурацию. – cacert

+0

Если вы добавляете простой элемент, как показано ниже, в классе конфигурации весна находит его[email protected] OctopusPropertiesRepository octopusPropertiesRepository –

ответ

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

    } 
+0

не вы имеете в виду @PostConstruct? – gybandi

+1

Да @PostConstruct извините. ... –

+0

Я не знаю, нужно ли вручную создать экземпляр компонента PropertySourcesPlaceholderConfigurer Bean вручную или загрузить Spring автоматически. –

0

Аналогичная проблема рассматривается в 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; 
    } 
} 

Вернитесь, если это решение работает или нет.

+0

Я пробовал, но одно и то же исключение :( – cacert

1

Согласно @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 получает экземпляр перед любой зависимостью, необходимой для спящего режима и 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 здесь, так что источник данных настроен соответствующим образом.

+1

хорошие моменты, я не знал упомянутых частей и пытался с надеждой, но все же ошибка :( – cacert

+0

да, попробовал, тоже, для меня тоже ошибка, позвольте мне немного рассказать, я вернусь к вам – gybandi

Смежные вопросы