Spring: доступ к основным компонентам через ApplicationContext - PullRequest
0 голосов
/ 24 октября 2011

Если в моем ApplicationContext есть 2 компонента, реализующих один и тот же интерфейс, я могу пометить один из них как основной в определении компонента. Этот компонент предпочтителен для внедрения зависимостей.

Есть ли способ получить прямой доступ с помощью ApplicationContext к основному без DI?

Ответы [ 3 ]

6 голосов
/ 24 октября 2011

Есть много разных способов сделать это.

  1. Установите primary = "true" в определении основного компонента. Когда это установлено, если есть несколько кандидатов на автоматическое подключение, первичному будет предоставлен более высокий приоритет.

    <beans ...>
      <bean id="myPrimaryBeanId" class="mypackage.MyInterface" primary="true"/>
      <bean id="mySecondaryBeanId" class="mypackage.MyInterface" />
    </beans> 
    
  2. В качестве альтернативы, установите autowire -андидат = "ложь" для неосновных компонентов, если вы думаете, что этот компонент не должен автоматически подключаться ни к одному компоненту. Однако при определении другого bean-компонента с тем же интерфейсом необходимо соблюдать осторожность, так как если вы забудете добавить это, снова будет несколько основных bean-компонентов.

    <beans ...>
      <bean id="myPrimaryBeanId" class="mypackage.MyInterface"/>
      <bean id="mySecondaryBeanId" class="mypackage.MyInterface"
          autowire-candidate="false"/>
    </beans>    
    
  3. Более подробно об аннотациях автоматической разводки можно использовать именованные зависимости, которые можно архивировать с помощью аннотации @ javax.annotation.Resource, как показано ниже. Это уменьшит сложность кода, чтобы выяснить, какой бин мог быть внедрен, поскольку можно просто определить местонахождение бина по его идентификатору.

    @Resource(name="myPrimaryBeanId")
    protected MyInterface myInstance;
    

Метод не-зависимой инъекции (DI)

Если вы предпочитаете не использовать DI, вы можете использовать следующее для извлечения компонента по имени из ApplicationContext

MyInterface myInstance = (MyInterface) 
    applicationContext.getBean("myPrimaryBeanId");

Если вы хотите использовать метод, отличный от DI, но из пружинного компонента, и если у вас нет дескриптора для контекста Spring, чтобы сделать это, вы можете изменить свой класс для реализации org.springframework.context.ApplicationContextAware интерфейс, который потребует от вас реализации метода setApplicationContext (ApplicationContext), в который Spring будет вставлять дескриптор в текущий контекст приложения, как показано ниже.

public class MyBean implements ApplicationContextAware {

  private ApplicationContext applicationContext;

  private String MY_PRIMARY_BEAN_ID = "myPrimaryBeanId";

  public void myMethod() {
    MyInterface myInstance = getMyPrimaryBean();

    // do my logic here
  }

  private MyInterface getMyPrimaryBean() {
    return (MyInterface) applicationContext.getBean(MY_PRIMARY_BEAN_ID);
  }

  @Override
  public void setApplicationContext(ApplicationContext applicationContext)
      throws BeansException {
    this.applicationContext = applicationContext;
  }

}

Примечание: Этот ответ основан на Spring 2.5.x

1 голос
/ 24 октября 2011

Сначала вам нужен ваш BeanFactory / ApplicationContext.Вы можете получить его, например, с помощью реализации BeanFactoryAware.Предполагая, что это ConfigurableListableBeanFactory, вы можете проверить, что является первичным для данного типа, например:

  ConfigurableListableBeanFactory clbf =
        (ConfigurableListableBeanFactory)beanFactory;
  String[] beanNames = clbf.getBeanNamesForType(myType);
  for (String beanName : beanNames) {
     BeanDefinition bd = clbf.getBeanDefinition(beanName);
     if (bd.isPrimary()) {
        ...
     }
  }
0 голосов
/ 24 октября 2011

Просто объявите его как Bean и установите зависимость вручную, выбрав из ApplicationContext и установив его. Но ты сломаешь Инверсия Контроля

...