【问题标题】:Null Inner Bean with Spring IoC使用 Spring IoC 的 Null 内部 Bean
【发布时间】:2009-02-12 10:25:20
【问题描述】:

我有一个像这样的单例 bean 定义:

<bean id="exampleBean" class="com.examples.ExampleBean">
  <property name="exampleBean2">
    <bean class="com.examples.ExampleBean2" />
  </property>
</bean>

ExampleBean 可能在哪里:

public class ExampleBean {
  private ExampleBean2 exampleBean2;

  public ExampleBean() { }

  public ExampleBean2 getExampleBean2() { return exampleBean2; }
  public void setExampleBean2(ExampleBean2 exampleBean2) { this.exampleBean2 = exampleBean2; }
}

问题在于,在某些情况下,com.examples.ExampleBean2 class 可能在运行时不存在,当 IoC 尝试实例化 exampleBean 时会导致错误。

我需要忽略来自 IoC 的此错误,并允许创建 exampleBean,但保留 exampleBean2 属性 null

所以问题是:这有可能吗?

感谢您的所有帮助。

【问题讨论】:

  • com.examples.ExampleBean2 是单例吗?
  • 实际上 ExampleBean 和 ExampleBean2 都是单例 bean,因为我认为它是 Spring IoC 默认范围

标签: java spring dependency-injection inversion-of-control


【解决方案1】:

如果你使用自动装配,你想达到的都是可能的。

<bean class="com.examples.ExampleBean" autowire="byType" />
<bean class="com.examples.ExampleBean2" />

或通过注释

@Autowired(required=false)
ExampleBean2 exampleBean2;

【讨论】:

    【解决方案2】:

    是否可以在您的 ExampleBean 上声明一个 init-method,并在此 init-method 中检查 ExampleBean2 类是否存在,如果存在则设置它?

    <bean id="exampleBean" class="com.examples.ExampleBean" init-method="init"/>
    

    也许在这里做事的更好方法是使用某种形式的 NullPattern,您总是提供 ExampleBean2 的实现,即使它只是它的“null”值。 p>

    【讨论】:

    • eljenso,我来看看 init-method。我已经有一个解决方法,这类似于您描述的 NullPattern。谢谢。 +1
    【解决方案3】:

    如果我做对了,当 Spring 尝试实例化 bean 时,不会加载 ExampleBean2。这个对吗?在这种情况下,我不认为你可以用 Spring 的内置功能做很多事情。

    也许您可以创建一个始终存在的容器类。此类将检查是否加载了 ExampleBean2,如果是,它将实例化它的一个实例。容器类将有一个 Object 属性,该属性可以是 null 也可以是 ExampleBean2 的实例。

    【讨论】:

    • kgiannakakis,ExampleBean2 在 ExampleBean 被实例化时被加载。即使 ExampleBean2 因为类不存在而失败,我仍然想实例化 ExampleBean。我已经有一个解决方法,这与你描述的类似。谢谢。 +1
    【解决方案4】:

    也许lazy-init 会这样做,但我认为spring 至少会在创建应用程序上下文时检查bean 实现类是否可用

    【讨论】:

    • Michael,lazy-init 没有解决它,因为当 exampleBean 被实例化时,它的所有依赖项也都被实例化(无论是否惰性),其中包括 exampleBean2
    【解决方案5】:

    也许这会起作用:

    public class NullFactoryBean implements FactoryBean {
    
        @Override
        public Object getObject() throws Exception {
            return null;
        }
    
        @Override
        public Class<?> getObjectType() {
            return Object.class;
        }
    
        @Override
        public boolean isSingleton() {
            return false;
        }
    
    }
    

    然后……

    public class ClassNotFoundPostProcessor implements BeanFactoryPostProcessor {
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
            for (String beanDefinitionName : beanDefinitionNames) {
                BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanDefinitionName);
                String beanClassName = beanDefinition.getBeanClassName();
                try {
                    Class.forName(beanClassName);
                } catch (ClassNotFoundException e) {
                    beanDefinition.setBeanClassName(NullFactoryBean.class.getName());
                }
            }
        }
    
    }
    

    然后……

    <beans>
        <bean id="exampleBean" class="com.examples.ExampleBean">
            <property name="exampleBean2">
                <bean class="com.examples.ExampleBean2" />
            </property>
        </bean>
    
        <bean class="ClassNotFoundPostProcessor" />
    </beans>
    

    编辑:很抱歉,这似乎没有抓住内部豆子。我在测试时错过了这个细节。它只捕获顶级bean。顺便说一句,com.examples.ExampleBean 可能无论如何都不会加载,因为它本身直接依赖于 ExampleBean2 类,虚拟机找不到该类,从而导致错误

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多