【问题标题】:Spring DI - do not initialise all the dependent beansSpring DI - 不要初始化所有依赖的bean
【发布时间】:2011-11-14 11:48:55
【问题描述】:

我有一个依赖于 ServiceB 的 ServiceA。 serviceB 来自一个带有 lazy-init=true 的 spring bean 文件,即我只希望 serviceB 在我请求该 bean 时被初始化。

但是,我确实在整个应用程序中使用 ServiceA,并且当我们执行基于 setter 的注入时,ServiceB 会被初始化。

我希望 ServiceA 不初始化 ServiceB直到ServiceA 中任何需要 ServiceB 的方法被调用。这样做的一种方法是使用 Aspects 但我正在寻找最简单的解决方案,特别是在 serviceB 的 Spring XML 文件或 serviceB 中的一些注释或任何代理标志中。

【问题讨论】:

标签: java spring inversion-of-control


【解决方案1】:

我认为LazyInitTargetSource 可以满足您的需求。

在初始化时需要代理引用但实际目标对象在首次使用之前不应初始化时很有用。当目标 bean 定义在 ApplicationContext(或急切预实例化单例 bean 的 BeanFactory)中时,它也必须标记为“lazy-init”,否则它将在启动时由所述 ApplicationContext(或 BeanFactory)实例化。

【讨论】:

    【解决方案2】:

    http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/aop/framework/autoproxy/target/LazyInitTargetSourceCreator.html 讨论了您可能想尝试的另一种方法:

    [LazyInitTargetSourceCreator is a] TargetSourceCreator 为每个 bean 强制执行 LazyInitTargetSource 这被定义为“惰性初始化”。这将导致为 每个 bean,允许获取对此类 bean 的引用 没有实际初始化目标 bean 实例。

    注册为自动代理的自定义 TargetSourceCreator 创建者,结合特定 bean 的自定义拦截器或 仅用于创建惰性初始化代理。例如,作为 在 XML 应用程序上下文中自动检测到的基础设施 bean 定义:

     <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
       <property name="customTargetSourceCreators">
         <list>
           <bean class="org.springframework.aop.framework.autoproxy.target.LazyInitTargetSourceCreator"/>
         </list>
       </property>
     </bean>
    
     <bean id="myLazyInitBean" class="mypackage.MyBeanClass" lazy-init="true">
       ...
     </bean>
    

    如果您发现自己在应用程序上下文中多次执行此操作,这将节省配置。

    【讨论】:

      【解决方案3】:

      我不了解 Spring,但在 Guice 中,您会使用 Provider&lt;ServiceB&gt;,因此当您准备好使用该服务时,您会使用 provider.get().callMethodOnB(...)

      我相信这是 JSR-330 规范的一部分,因此在 Spring 中可能存在等效的东西(我已经有一段时间没有使用 Spring 的最新版本了)。

      【讨论】:

      • 立即查看!如果您要投反对票,请留下便条说明原因不是很有礼貌吗?
      【解决方案4】:

      您也可以使用method injection。 通常,需要从上下文中获取单例 bean 的新实例,但也可以在您的情况下使用它。

      示例:

      package org.test.lazy;
      
      public abstract class ParentBean {
          public abstract LazyBean getLazy();
          public void lazyDoingSomething() {
              getLazy().doSomething();
          }
      }
      

      package org.test.lazy;
      
      public class LazyBean {
         public void init() {
             System.out.println("Initialized");
         }
         public void doSomething() {
             System.out.println("Doing something");
         }
      }
      

      package org.test.lazy;
      
      import org.junit.Test;
      import org.junit.runner.RunWith;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.test.context.ContextConfiguration;
      import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
      
      @ContextConfiguration
      @RunWith(SpringJUnit4ClassRunner.class)
      public class LazyTest {
      
          @Autowired
          private ParentBean parentBean;
      
          @Test
          public void test() {
              parentBean.lazyDoingSomething();
              parentBean.lazyDoingSomething();
          }
      }
      

      <?xml version="1.0" encoding="UTF-8"?>
      
      <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="
          http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      ">
          <import resource="classpath:org/test/lazy/Lazy-context.xml"/>
          <bean id="parentBean" class="org.test.lazy.ParentBean">
              <lookup-method bean="lazyBean" name="getLazy"/>
          </bean>
      </beans>
      

      <?xml version="1.0" encoding="UTF-8"?>
      
      <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="
          http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      "
      default-lazy-init="true">
      
          <bean id="lazyBean" class="org.test.lazy.LazyBean" init-method="init" />
      </beans>
      

      所以你的惰性 bean 只会按需初始化一次。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-07-08
        • 1970-01-01
        • 2014-11-16
        • 2023-03-02
        • 1970-01-01
        • 2020-10-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多