2011-11-14 60 views
6

我有一個ServiceB,它依賴於ServiceB。 serviceB來自lazy-init = true的spring bean文件,也就是說,我只希望serviceB在需要的時候初始化。Spring DI - 不初始化所有依賴bean

但是我在整個應用程序中都使用ServiceA,並且當我們執行基於setter的注入時ServiceB被初始化。

我希望ServiceA不初始化ServiceB ,直到 ServiceA中的任何方法被調用,需要ServiceB。這樣做的一種方法是使用方面,但我正在尋找最簡單的可能解決方案,尤其是在serviceB的spring xml文件或serviceB中的某些註釋或任何代理標誌中。

有人可以幫忙嗎?

+0

可能重複的[春天有沒有一個春天的懶惰代理工廠?](http://stackoverflow.com/questions/2391168/is-there-a-spring-lazy-proxy-factory-in-spring) – skaffman

+0

將ServiceB工廠傳遞給ServiceA怎麼樣? –

回答

6

我認爲LazyInitTargetSource做你所需要的。

有用時,需要在初始化代理參考,但實際的目標對象不應該被初始化,直到第一次使用。當在ApplicationContext中定義目標bean時(或者是急於預先實例化單例bean的BeanFactory),它也必須標記爲「lazy-init」,否則它將在啓動時由所述ApplicationContext(或BeanFactory)實例化。

0

我不知道春天,但在Guice你會使用Provider<ServiceB>,所以當你準備好使用服務時,你會去provider.get().callMethodOnB(...)。我相信這是JSR-330規範的一部分,所以有可能在Spring中有相同的東西(我還沒有使用Spring的最新版本很長一段時間)。

+1

現在看!如果你打算倒戈,留下一張紙條說明原因是否禮貌? – dty

0

您也可以使用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只會根據需求初始化一次。

1

,你可能會想嘗試在http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/aop/framework/autoproxy/target/LazyInitTargetSourceCreator.html討論另一種方法:

[LazyInitTargetSourceCreator是]的TargetSourceCreator在施行LazyInitTargetSource爲每個bean 被定義爲「懶惰初始化」。這將導致爲這些bean中的每一個創建一個 的代理,允許在不實際初始化目標bean實例的情況下獲取對這樣的bean的引用 。

要爲自動代理 創建者註冊爲自定義TargetSourceCreator,並結合特定Bean的自定義攔截器或僅用於創建lazy-init代理的 。例如, 自動檢測基礎設施豆在XML應用程序上下文定義 :

<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> 

如果你發現自己在一個應用程序上下文做了幾次,這將節省的配置。