【问题标题】:Spring: access primary beans via ApplicationContextSpring:通过 ApplicationContext 访问主 bean
【发布时间】:2011-10-24 11:59:42
【问题描述】:

如果我的 ApplicationContext 中有 2 个 bean 实现了相同的接口,我可以在 bean 定义中将其中一个标记为主要的。这个 bean 是依赖注入的首选。

有没有办法在没有 DI 的情况下使用 ApplicationContext 直接访问主要的?

【问题讨论】:

标签: java spring dependency-injection javabeans autowired


【解决方案1】:

有很多不同的方法可以做到这一点。

  1. 在主 bean 定义中设置 primary="true"。设置后,如果有多个候选自动布线,则优先级更高。

    <beans ...>
      <bean id="myPrimaryBeanId" class="mypackage.MyInterface" primary="true"/>
      <bean id="mySecondaryBeanId" class="mypackage.MyInterface" />
    </beans> 
    
  2. 或者,如果您认为此 bean 根本不应该自动连接到任何 bean,请为非主 bean 设置 autowire-candidate="false"。但是,在定义另一个具有相同接口的bean时需要小心,如果忘记添加这个,就会再次出现多个主bean。

    <beans ...>
      <bean id="myPrimaryBeanId" class="mypackage.MyInterface"/>
      <bean id="mySecondaryBeanId" class="mypackage.MyInterface"
          autowire-candidate="false"/>
    </beans>    
    
  3. 通过使用命名依赖项更具体地了解自动连接注解,可以使用@javax.annotation.Resource 注解进行归档,如下所示。这将降低找出可能被注入的 bean 的代码复杂性,因为可以简单地通过 id 定位 bean。

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

非依赖注入 (DI) 方法

如果您不喜欢使用 DI,可以使用以下方法从 ApplicationContext 中按名称获取 bean

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

如果您想使用非 DI 方法,但使用 spring bean,并且如果您没有 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

【讨论】:

    【解决方案2】:

    首先你需要你的 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()) {
            ...
         }
      }
    

    【讨论】:

      【解决方案3】:

      只需将其声明为 Bean 并通过从 ApplicationContext 获取并设置它来手动设置依赖项。但是你会破坏控制反转

      【讨论】:

      • 不幸的是,在这种情况下,我无法确定哪个 bean 是主要的,因为我只能从上下文中获取名称和 bean 本身。我无权访问 bean 定义元数据。
      • 在上下文中有两个具有相同 id 的 bean 并不能真正节省。有时它可以工作,但 Spring 不推荐它。
      • 我很困惑。能否请您重述您的问题
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-17
      • 2011-07-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多