2009-07-28 39 views
8

Tôi đang xử lý cơ sở mã kế thừa trong đó một lớp không có dây vào mùa xuân cần có lớp học có dây vào mùa xuân. Tôi đã hy vọng tạo ra một lớp nhà máy đã được kết nối khi khởi động và sau đó tôi có thể gọi phương thức getInstance() để lấy một đối tượng có dây. cách tốt nhất để làm việc này là gì?Dây mùa xuân lớp tĩnh

Ví dụ:

public class LegacyA { 
    public void doSomething() { 
     ... 
     Foo foo = FooFactory.getInstance(); 
     ... 
    } 
} 

public class FooFactory { 
    private static Foo foo; 

    public static Foo getInstance() { 
     if (foo == null) throw new IllegalStateException(); 
     return foo; 
    } 
} 

Tôi cần FooFactory được dây lên khi khởi động để LegacyA chỉ đơn giản có thể gọi getInstance() để nó trả về một thể hiện của Foo (mà cũng là một bean được định nghĩa trong bối cảnh ứng dụng).

<bean id="legacyA" class="LegacyA"/> 

<bean id="foo" class="Foo"/> 

<!-- I need this bean to be injected with foo so that the FooFactory can return a foo --> 
<bean id="fooFactory" class="FooFactory"/> 

Edit: Tôi đã phải tái làm việc ví dụ của tôi một chút như tôi đã nhận nó một chút confuzzled trong đầu của riêng tôi ...

+0

Foo được tiêm vào FooFactory như thế nào? Một setter, constructor, ...? – wds

Trả lời

10

Sử dụng tĩnh như thế này thực sự đi ngược lại các hạt mùa xuân IoC, nhưng nếu bạn thực sự để sử dụng chúng, sau đó tôi sẽ đề nghị viết một móc mùa xuân đơn giản mà mất Foo và tiêm nó vào FooFactory, ví dụ

public class FooFactoryProcessor implements InitializingBean { 

    private Foo foo; 

    public void setFoo(Foo foo) { 
     this.foo = foo; 
    } 

    public void afterPropertiesSet() throws Exception { 
     Foofactory.setFoo(foo); 
    } 
} 

Và trong XML của bạn:

<bean id="foo" class="Foo"/> 

<bean class="FooFactoryProcessor"> 
    <property name="foo" ref="foo"/> 
</bean> 

Không cần phải sửa đổi Foo hoặc FooFactory

+0

đã đồng ý liên quan đến nhận xét tĩnh của bạn. Tôi thường không bao giờ đi xuống con đường đó, tuy nhiên mã di sản sử dụng lớp tĩnh này khắp nơi và cách tốt nhất để móc trong đối tượng mùa xuân mới này mà không vi phạm mã hiện có là giữ các cuộc gọi đến lớp tĩnh cũ và có tĩnh đó lớp sử dụng đối tượng có dây mùa xuân mới và cải tiến. – digiarnie

+2

Tại sao bạn không chỉ để mùa xuân quản lý FooFactory trực tiếp. Bạn không thực sự cần sự trừu tượng là "FooFactoryProcessor". Bạn có thể thêm một thiết lập thuộc tính không tĩnh vào FooFactory để thiết lập foo trên nó. –

+0

Điều này đúng, vâng, nhưng tôi đã đi dọc theo các dòng số lượng nhỏ nhất của những thay đổi đối với mã di sản, đó là những gì OP dường như sau. – skaffman

1

là định đậu như một singleton trong cấu hình Spring sử dụng đây ? Sau đó bạn có thể tiêm nó vào LegacyB bằng cách sử dụng thuộc tính hoặc hàm tạo (tùy chọn của tôi là sau) và sau đó chỉ có một cá thể có sẵn.

EDIT: Re. câu hỏi đã thay đổi của bạn (!) Tôi không chắc chắn tại sao bạn không chỉ đơn giản là tiêm Foo một lần nữa như một singleton vào nhà máy của bạn. Cũng lưu ý rằng bạn có thể sử dụng phương thức getInstance() thông qua cấu hình Spring bằng cách sử dụng factory-method và duy trì tiêm qua tất cả các lớp.

+0

Xin lỗi vì phải thay đổi câu hỏi một chút về bạn. Tôi đã không nhận ra cho đến một chút sau khi tôi đã có toàn bộ câu hỏi sai trong đầu của tôi. – digiarnie

+0

Cảm ơn những người đứng đầu. Đó không phải là một vấn đề. Câu trả lời được sửa đổi một cách thích hợp. –

1

Ngoài skaffman của trả lời bạn cần phải hết sức cẩn thận về trật tự khởi tạo.

Khi chỉ sử dụng Spring bean, framework sẽ tự động tìm ra thứ tự khởi tạo đúng thứ tự. Ngay sau khi bạn đang làm thủ thuật singleton tuy nhiên, điều này có thể phá vỡ nếu bạn không cẩn thận.

Nói cách khác hãy đảm bảo rằng LegacyA không thể chạy trước khi bối cảnh ứng dụng kết thúc tải.

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