Optional Spring bean references

后端 未结 5 1999
逝去的感伤
逝去的感伤 2020-12-03 17:22

In my application I am using ContextLoaderListener to load context files from many jars using:


    contextConfigLocat         


        
相关标签:
5条回答
  • 2020-12-03 17:26

    what method do you recommend for handling dynamic references?

    I think @cristian's @Autowired answer is a good one. That will call the setter methods if the beans of that type are available. However, if you have multiple beans of the same type, I believe Spring throws an exception. If you cannot use @Autowired for this or some other reason, I see a couple of solutions:

    1. You could make your class ApplicationContextAware and lookup the beans in the context yourself:

      public void setApplicationContext(ApplicationContext applicationContext) {
          if (applicationContext.containsBean("optionalBeanReference1")) {
              setOptionalBeanReference1(
                  (OptionalBeanReference1)applicationContext.bean(
                      "optionalBeanReference1");
          }
          ...
      }
      
    2. You could invert the dependency. Each of the optional classes could set themselves on the mainAppBean. I use this in certain situations when a direct dependency would cause loops or other problems.

      <bean id="optionalBeanReference1" class="com.someapp.SomeClass">
          <constructor-arg index="0" ref="mainAppBean"/>
      </bean>
      

      Then in the SomeClass:

      public SomeClass(com.someapp.MyApplication mainAppBean) {
          mainAppBean.setOptionalBeanReference1(this);
      }
      
    3. You could stay with your direct dependency and then either import a file with the beans defined or import another file where you define the beans as having null values by using a factory bean. See this factory code.

    Good luck.

    0 讨论(0)
  • 2020-12-03 17:28

    With recent versions of Spring (tested with spring 4.1) and Java Configuration and Java 8, you can use Optional in parameters, and are only autowired if available.

    @Autowired
    public MyApplication(Optional<YourOptionalObject> maybeObject) {
        // do something with the optional autowired
    }
    
    0 讨论(0)
  • 2020-12-03 17:31

    There's no built-in mechanism for this. However, you could write a pretty trivial FactoryBean implementation to do this for you, something like this:

    public class OptionalFactoryBean extends AbstractFactoryBean<Object> implements BeanNameAware {
    
        private String beanName;
    
        @Override
        public void setBeanName(String beanName) {
            this.beanName = BeanFactoryUtils.originalBeanName(beanName);
    
        }
    
        @Override
        protected Object createInstance() throws Exception {
            if (getBeanFactory().containsBean(beanName)) {
                return getBeanFactory().getBean(beanName);
            } else {
                return null;
            }
        }
    
        @Override
        public Class<?> getObjectType() {
            return null;
        }
    }
    

    You can then use it like this:

    <bean id="mainAppBean" class="com.someapp.MyApplication">
        <constructor-arg index="0" ref="localBean"/>    
        <constructor-arg index="1">
           <bean name="optionalBeanReference1" class="com.someapp.OptionalBeanFactory"/>
        </constructor-arg>
        <constructor-arg index="2">
           <bean name="optionalBeanReference2" class="com.someapp.OptionalBeanFactory"/>
        </constructor-arg>
    </bean>
    
    0 讨论(0)
  • 2020-12-03 17:39

    Given that the bean references in your XML config are defined via expression language (EL) you can do the following:

    <property name="cache" value="#{getObject('optionalCache')}" />
    

    which makes use of the BeanExpressionContext.getObject() method. See here for more details.

    0 讨论(0)
  • 2020-12-03 17:40

    My best guess is to use autowire-ing with required false. Don't know how you can express this in XML but using annotation configuration this would look like:

    @Autowired(required=false)
    
    0 讨论(0)
提交回复
热议问题