Как ввести Bean в xml из метода (@Bean), который возвращает интерфейс (com.typesafe.config.Config)?

У меня есть приложение spring на основе xml-config, где один из моих bean-компонентов требует в качестве параметра конструктора параметр com.typesafe.config.Config. Для этой цели у нас есть класс @Configuration, в котором один из методов (обозначенный как @Bean) возвращает объект com.typesafe.config.Config.

Но когда весна начинается, он жалуется, что «Не удалось создать экземпляр [com.typesafe.config.Config]: указанный класс является интерфейсом»

Как внедрить возвращаемый объект getconfig в конструктор через xml?

Вот фрагмент кода, упрощенный, чтобы избавиться от логики приложения:

import com.typesafe.config.Config;
...
public class myFilter implements Filter {
  public myFilter(Config aconfig) {
        ...
  }
}

Затем у меня есть следующий класс JavaConfig, который создает bean-компонент, который мне нужно внедрить в конструктор myFilter:

@org.springframework.context.annotation.Configuration
public class TSConfiguration {
   ...
   @Bean(name = "app-config")
   public Config getConfig() {
     ...
   }
}

Я добавил в свой файл spring.xml следующее:

<beans:bean class="TSConfiguration" />
<beans:bean id="app-config" class="com.typesafe.config.Config"/>
<beans:bean id="theFilter" class="myFilter">
   <beans:constructor-arg index="0" ref="app-config"/>
 </beans:bean>

Вот исключение из Spring:

15-Feb-2017 13:19:55.463 SEVERE [localhost-startStop-1] org.springframework.web.context.ContextLoader.initWebApplicationContext Context initialization failed
 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'app-config' defined in ServletContext resource [/WEB-INF/spring-security.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.typesafe.config.Config]: Specified class is an interface

Спасибо.




Ответы (2)


Оскорбительная строка такова:

<beans:bean id="app-config" class="com.typesafe.config.Config"/>

Поскольку вы поместили это в свой spring.xml, Spring пытается создать экземпляр bean-компонента с именем app-config из Config. Но Config — это интерфейс, поэтому Spring не может создать его экземпляр и, следовательно, ошибка.

Я думаю, что как только вы удалите его, Spring выберет @Bean, который вы создали с помощью getConfig. Если это не сработает, проверьте, правильно ли TSConfiguration импортируется в ваш файл spring.xml.

person ketan vijayvargiya    schedule 15.02.2017
comment
Я попытался удалить его, но все равно не работает. удалив эту строку определения bean-компонента, я получил Невозможно разрешить ссылку на bean-компонент «app-config» при установке аргумента конструктора; вложенным исключением является org.springframework.beans.factory.NoSuchBeanDefinitionException: компонент с именем «app-config» не определен - person MDot; 15.02.2017
comment
Я не получил никаких ошибок от bean-компонента TSConfiguration. - person MDot; 16.02.2017
comment
Я не получил никакой ошибки от bean-компонента TSConfiguration: для удаления определения bean-компонента myFilter требуется конфигурация приложения, другие исключения не выдаются. Я ушел в TSConfiguration, и ошибок не было. - person MDot; 16.02.2017
comment
Я думаю, что на ваш первоначальный вопрос дан ответ. Следующий - это зависит от того, как вы импортируете одну конфигурацию в другую. Можете ли вы обновить это? Кроме того, почему вы не можете создать экземпляр myFilter внутри TSConfiguration? Это было бы проще - person ketan vijayvargiya; 16.02.2017
comment
Вопрос заключался в том, как мне ввести возвращаемый объект getconfig в конструктор через xml?. Я еще не нашел решения. TSConfiguration является частью модуля, совместно используемого другими веб-приложениями, в то время как мой фильтр необходимо создать из существующего xml в этом веб-приложении, чтобы получить безопасную для типов конфигурацию. - person MDot; 16.02.2017

Чтобы добавить к другому ответу, вы дважды объявляете то, что, вероятно, должно быть одним и тем же компонентом.

Здесь вы говорите Spring создать bean-компонент типа Config с именем app-config:

 @Bean(name = "app-config")
 public Config getConfig(){

Здесь вы пытаетесь создать еще один bean-компонент типа Config с идентификатором app-config.

 <beans:bean id="app-config" class="com.typesafe.config.Config"/>

Если вы объявляете bean-компонент в JavaConfig, нет необходимости снова объявлять его в XML и наоборот (при условии, что вы намерены иметь один bean-компонент этого типа).

И, как уже было указано, вы не можете создать экземпляр интерфейса.


Обновлено:

Я собираюсь в основном наполовину проигнорировать код, который вы опубликовали, так как, похоже, есть непонимание того, что делают аннотации и как их использовать.

Во-первых, если вы хотите сделать все в чистом XML, вы не можете сделать это:

<beans:bean id="app-config" class="com.typesafe.config.Config"/>

Вам нужно сделать конкретную реализацию этого интерфейса. Но, судя по тому, что вы опубликовали, у вас есть класс конфигурации, который вы используете. Начнем с этого:

package com.testpackage;

@Configuration
public class Config {


        @Bean
        public SomeInterface someImplementation(){
            return new SomeInterface() {
                @Override
                public String implementation() {
                    return "String";
                }
            };
        }
    }

Это говорит о создании bean-компонента типа SomeInterface. Имя этого компонента унаследует имя метода someImplementation, поэтому нет смысла давать ему имя вручную. Обратите внимание, что хотя это возвращает интерфейс, мы создаем анонимный класс и возвращаем его.

Далее мы рассмотрим XML для приведенного выше:

<beans>
        <context:component-scan base-package="com.testpackage"/>

        <bean class="com.testpackage.ConcreteClass">
            <constructor-arg index="0" ref="someImplementation"/>
        </bean>
</beans>

Обратите внимание, что мы сканируем (context:component-scan) пакет с конфигурацией в нем. Если мы используем аннотацию @Configuration, мы можем выполнить сканирование компонентов.

Пример ниже делает то же самое, но только вручную объявляет bean-компонент Configuration:

<beans>
        <bean class="com.testpackage.Config"/>

        <bean class="com.testpackage.ConcreteClass">
            <constructor-arg index="0" ref="someImplementation"/>
        </bean>
</beans>

Если вы вручную объявляете класс Config, как описано выше, вам не нужно аннотировать его с помощью @Configuration. Смысл этой аннотации в том, чтобы сканирование компонента «увидело» компонент и создало его экземпляр. Поскольку мы делаем это вручную, аннотация не требуется.

И, для полноты картины, это модульный тест, который проверяет, что все работает:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:META-INF/appContextTest.xml"})
public class SomeTester {


    @Autowired
    ConcreteClass concreteClass;

    @Test
    public void test(){
        assertEquals("String", concreteClass.impl.implementation());
    }
}
person Christopher Schneider    schedule 15.02.2017
comment
Последующая весенняя документация JavaConfig docs.spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/ компонент должен быть объявлен в формате xml. Более того, при сканировании компонентов @Bean не предназначен для автоматического обнаружения. - person MDot; 16.02.2017
comment
Намерение состоит в том, чтобы использовать в определении bean-компонента xml bean-компонент, определенный с помощью JavaConfig. Следуя этому руководству, документы .spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/ (с несколькими обновлениями, связанными с удалением ConfigurationPostProcessor) Я столкнулся с проблемой. Я пытаюсь объявить его, потому что он не вводится автоматически, и его нужно передать конструктору myFilter. - person MDot; 16.02.2017
comment
В этой документации нет ничего, что говорило бы о том, что это должно быть и в XML, и в JavaConfig. Он не должен быть в обоих местах. Ваш вопрос немного неясен на данный момент. Вы должны сделать новый с полным примером проблемы, которую вы пытаетесь решить. На ваш существующий вопрос дан правильный ответ. - person Christopher Schneider; 17.02.2017
comment
Вопрос был в том, как мне ввести возвращаемый объект getconfig в конструктор через xml? Я не думаю, что на него ответили. В предыдущем ответе было предложено удалить оскорбительную строку, я пытался, но это все равно не работает. Какой ответ на вопрос? - person MDot; 17.02.2017
comment
Я полагаю, вы правы. По правде говоря, у вас есть несколько проблем в предоставленном вами коде, поэтому нет гарантии, что вы не сделали что-то неправильно (в основном, вы сильно смешиваете Java Config и XML, который делает одно и то же дважды). Я обновлю свой ответ основным примером. - person Christopher Schneider; 17.02.2017