2017-01-02 2 views
0

У меня есть некоторые java-объекты, которые поступают из внешней библиотеки, которые мне нужно вводить в моем весеннем проекте. Проблема заключается в том, что классы из библиотеки не знают о каком-либо весной API,POJO Injection in Spring похож на CDI

Если я впрыснуть бобы из библиотеки услуг с использованием @Autowired Я получаю org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type

Ниже мой класс обслуживания

@Path("/test") 
public class TestService { 

    @Autowired 
    SomeOtherClass service; 

    @GET 
    public Response get(){ 
     return Response.ok(service.someMethod()).build(); 
    } 
} 

и Ниже мой класс из библиотеки, которая не знает весной

public class SomeOtherClass { 

    public String someMethod(){ 
     return "Data from library"; 
    } 
} 

Когда я вызываю мою службу я получаю исключение, как

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.SomeOtherClass' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 

Есть ли весной вес, чтобы ввести простой Java-объект, аналогичный впрыску в **CDI**? Существует один вариант определения applicationcontext.xml и определение SomeOtherClass в xml и использование getBean, но я не хочу этого делать. Есть ли другой вариант?

Примечание:

Эти варианты не могут рассматриваться, потому что у меня есть 100's классов, поступающих из библиотеки

  1. Cannot use applicationcontext.xml

  2. Cannot @Configuration @Bean to produce beans.

+1

Вам не нужно 'getBean', вам просто нужно объявить экземпляр' SomeOtherClass', тогда '@ Autowired' будет работать. Весна будет вводить только управляемые бобы (так же, как CDI, если что-то не управляется, оно ничего не будет вводить). –

+1

Тогда не используйте весну ... Вам нужно, чтобы эти классы были известны как управляемые экземплярами Spring, если вы этого не сделаете, это не сработает. Если вы не можете (или не будете) использовать конфигурацию на основе xml или java, это не так много, что может помочь весна. (Хотя вы могли бы продлить весну, чтобы обнаружить/проверить эти классы, но для этого потребуются некоторые знания о внутренних деталях и работе весны). –

ответ

3

Вы можете использовать @Configuration и @Bean аннотаций следующим образом -

Создайте новый класс:

@Configuration 
public class AppConfig { 

    @Bean 
    SomeOtherClass someOtherClassBean(){ return new SomeOtherClass();} 

} 

Теперь автоматическая проводка должна работать. Что он делает, на самом деле создает боб и позволяет Spring узнать об этом.

+0

Я думал об этом, но у меня есть много классов (100), поступающих из библиотеки. Есть ли способ избежать написания «Конфигурация» и «Боб» и рассказать весне, чтобы вводить простые объекты в Autowire? –

+0

Этот код даже не компилируется ... –

+0

@ M. Deinum см. Редактирование. – gba

1

Может быть, попробуйте добавить бобы к программно контейнер IoC: Add Bean Programmatically to Spring Web App Context

Вы должны найти все классы, которые вы хотите создать экземпляр и использовать один из методов в связанном вопросе.

+0

Написание дополнительного кода для достижения инъекции аналогично настройке контекстного файла или бина. Я ищу некоторую поддержку из коробки, похожую на bean-discovery-mode = «ALL» в java ee –

+1

Я не уверен, что есть что-то подобное, даже имеет смысл (для меня), что нет. Мне кажется, что в большинстве случаев имеет смысл контролировать то, что входит в контейнер IoC. Надеюсь, вы найдете что-то полезное. Дайте нам знать :-) – gba

1

Вы можете использовать отражение, чтобы программно добавлять определения Bean.

@Override 
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { 
    Reflections ref = new Reflections(new ConfigurationBuilder() 
      .setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner()) 
      .setUrls(ClasspathHelper.forPackage(PACKAGE_NAME)) 
      .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix(PACKAGE_NAME)))); 
    ref.getSubTypesOf(Object.class).stream() 
      .forEach(clazz -> { 
       logger.info("Defining pojo bean: {} -> {}", Introspector.decapitalize(clazz.getSimpleName()), clazz.getCanonicalName()); 
       registry.registerBeanDefinition(Introspector.decapitalize(clazz.getSimpleName()), 
         BeanDefinitionBuilder.genericBeanDefinition(clazz).getBeanDefinition()); 
      }); 
} 

Впоследствии эти компоненты могут быть @Autowired в другом месте. См. Gist: https://gist.github.com/ftahmed/a7dcdbadb8bb7dba31ade463746afd04

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