2011-11-14 32 views
6

Tôi có ServiceA có sự phụ thuộc vào ServiceB. ServiceB xuất phát từ một tệp bean mùa xuân với lazy-init = true i.e, tôi chỉ muốn serviceB được khởi tạo khi và nếu tôi yêu cầu bean đó.Spring DI - không khởi tạo tất cả các bean phụ thuộc

Tuy nhiên, tôi sử dụng ServiceA trong suốt ứng dụng của mình và khi chúng tôi thực hiện dịch vụ tiêm dựa trên setB được khởi tạo.

Tôi muốn ServiceA không khởi tạo ServiceB cho đến bất kỳ phương thức nào trong ServiceA được gọi là cần ServiceB. Một cách để làm điều này là sử dụng các khía cạnh nhưng tôi đã xem xét giải pháp đơn giản nhất có thể cho điều này đặc biệt trong tệp xml mùa xuân cho serviceB hoặc một số chú thích trong serviceB hoặc bất kỳ cờ proxy nào.

Ai đó có thể trợ giúp?

+0

có thể trùng lặp của [Có nhà máy sản xuất proxy lười xuân vào mùa xuân không?] (Http://stackoverflow.com/questions/2391168/is-there-a-spring-lazy-proxy-factory-in-spring) – skaffman

+0

những gì về việc đi qua một nhà máy ServiceB vào ServiceA? –

Trả lời

6

Tôi nghĩ rằng LazyInitTargetSource sẽ làm những gì bạn cần.

Hữu ích khi tham chiếu proxy là cần thiết khi khởi tạo nhưng đối tượng đích thực không được khởi tạo cho đến khi sử dụng lần đầu. Khi bean mục tiêu được định nghĩa trong một ApplicationContext (hoặc BeanFactory đang háo hức trước các hạt đơn), nó phải được đánh dấu là "lazy-init", nếu không nó sẽ được khởi tạo bởi ApplicationContext (hoặc BeanFactory) khi khởi động.

0

Tôi không biết về Mùa xuân, nhưng trong Guice bạn sẽ sử dụng số Provider<ServiceB>, để khi bạn sẵn sàng sử dụng dịch vụ, bạn sẽ đến provider.get().callMethodOnB(...).

Đây là, tôi tin, một phần của thông số JSR-330, vì vậy có thể có một điều tương đương trong Spring (Tôi chưa sử dụng phiên bản cập nhật của Spring trong một thời gian dài).

+1

Xem ngay bây giờ! Nếu bạn đang đi để downvote, nó sẽ không được lịch sự để lại một lưu ý nói tại sao? – dty

0

Bạn cũng có thể sử dụng method injection. Như một quy luật, nó được yêu cầu để có được một trường hợp mới của một hạt đơn từ một bối cảnh, nhưng nó có thể được sử dụng trong trường hợp của bạn quá.

mẫu:

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> 

Vì vậy, bạn lười biếng đậu sẽ được khởi tạo chỉ một lần theo yêu cầu.

1

Một phương pháp mà bạn có thể muốn thử được thảo luận tại http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/aop/framework/autoproxy/target/LazyInitTargetSourceCreator.html:

[LazyInitTargetSourceCreator là a] TargetSourceCreator mà thi hành một LazyInitTargetSource cho mỗi đậu được định nghĩa là "lười biếng-init". Điều này sẽ dẫn đến một proxy được tạo cho mỗi hạt, cho phép tìm nạp tham chiếu đến một bean như vậy mà không thực sự khởi tạo phiên bản bean mục tiêu.

Để được đăng ký làm TargetSourceCreator tùy chỉnh cho người tạo tự động proxy người tạo, kết hợp với công cụ chặn tùy chỉnh cho các hạt cụ thể hoặc chỉ để tạo proxy lười-init. Ví dụ, như autodetected đậu cơ sở hạ tầng trong bối cảnh ứng dụng XML định nghĩa:

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

Nếu bạn thấy mình làm điều này nhiều lần trong một bối cảnh ứng dụng, điều này sẽ tiết kiệm được vào cấu hình.

Các vấn đề liên quan