2012-05-03 35 views
15

Sự tiếp tục từ Dependency injection, delayed injection praxis. Tôi có lớp Chính:Tiêm động lực mùa xuân, kiểu giống như nhà máy

package test; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.support.ClassPathXmlApplicationContext; 
import org.springframework.stereotype.Component; 

import java.util.List; 
import java.util.Scanner; 

@Component 
public class Main { 
    @Autowired 
    private StringValidator stringValidator; 

    @Autowired 
    private StringService stringService; 

    @Autowired 
    private ValidationService validationService; 

    public void main() { 
     scanKeyboardCreateLists(); 

     stringValidator.validate(); 

     final List<String> validatedList = stringValidator.getValidatedList(); 
     for (String currentValid : validatedList) { 
      System.out.println(currentValid); 
     } 
    } 

    private void scanKeyboardCreateLists() { 
     //Let's presume the user interacts with the GUI, dynamically changing the object graph... 
     //Needless to say, this is past container initialization... 
     Scanner scanner = new Scanner(System.in); 
     int choice = scanner.nextInt(); 

     //Delayed creation, dynamic 
     if (choice == 0) { 
      stringService.createList(); 
      validationService.createList(); 
     } else { 
      stringService.createSecondList(); 
      validationService.createSecondList(); 
     } 
    } 

    public static void main(String[] args) { 
     ApplicationContext container = new ClassPathXmlApplicationContext("/META-INF/spring/applicationContext.xml"); 
     container.getBean(Main.class).main(); 
    } 
} 

Và đồ thị đối tượng được tạo động, tùy thuộc vào tương tác của người dùng. Tôi đã giải quyết khớp nối ứng dụng, cho phép tôi kiểm tra điều này rất đơn giản. Ngoài ra, vì danh sách được duy trì bởi vùng chứa, tính chất động của ứng dụng này (và mọi thứ khác) không liên quan, vì chúng có thể được yêu cầu bất cứ lúc nào ứng dụng cần chúng, duy trì các yếu tố của chúng.

Phần còn lại của mã này là ở đây:

package test; 

import java.util.List; 

public interface Stringable { 
    List<String> getStringList(); 
} 

package test; 

import org.springframework.stereotype.Component; 

import java.util.ArrayList; 

@Component 
public class StringList extends ArrayList<String> { 
} 

package test; 

import org.springframework.stereotype.Component; 

import javax.inject.Inject; 
import java.util.ArrayList; 
import java.util.List; 

@Component 
public class StringService implements Stringable { 

    private List<String> stringList; 

    @Inject 
    public StringService(final ArrayList<String> stringList) { 
     this.stringList = stringList; 
    } 

    //Simplified 
    public void createList() { 
     stringList.add("FILE1.txt"); 
     stringList.add("FILE1.dat"); 
     stringList.add("FILE1.pdf"); 
     stringList.add("FILE1.rdf"); 
    } 

    public void createSecondList() { 
     stringList.add("FILE2.txt"); 
     stringList.add("FILE2.dat"); 
     stringList.add("FILE3.pdf"); 
     stringList.add("FILE3.rdf"); 
    } 

    @Override 
    public List<String> getStringList() { 
     return stringList; 
    } 
} 

package test; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Component; 

import java.util.ArrayList; 
import java.util.List; 

@Component 
public class StringValidator { 
    private List<String> stringList; 
    private List<String> validationList; 

    private final List<String> validatedList = new ArrayList<String>(); 

    @Autowired 
    public StringValidator(final ArrayList<String> stringList, 
          final ArrayList<String> validationList) { 
     this.stringList = stringList; 
     this.validationList = validationList; 
    } 

    public void validate() { 
     for (String currentString : stringList) { 
      for (String currentValidation : validationList) { 
       if (currentString.equalsIgnoreCase(currentValidation)) { 
        validatedList.add(currentString); 
       } 
      } 
     } 
    } 

    public List<String> getValidatedList() { 
     return validatedList; 
    } 
} 

package test; 

import java.util.List; 

public interface Validateable { 
    List<String> getValidationList(); 
} 

package test; 

import org.springframework.stereotype.Component; 

import java.util.ArrayList; 

@Component 
public class ValidationList extends ArrayList<String> { 
} 

package test; 

import org.springframework.stereotype.Component; 

import javax.inject.Inject; 
import java.util.ArrayList; 
import java.util.List; 

@Component 
public class ValidationService implements Validateable { 

    private List<String> validationList; 

    @Inject 
    public ValidationService(final ArrayList<String> validationList) { 
     this.validationList = validationList; 
    } 

    //Simplified... 
    public void createList() { 
     validationList.add("FILE1.txt"); 
     validationList.add("FILE2.txt"); 
     validationList.add("FILE3.txt"); 
     validationList.add("FILE4.txt"); 
    } 

    public void createSecondList() { 
     validationList.add("FILE5.txt"); 
     validationList.add("FILE6.txt"); 
     validationList.add("FILE7.txt"); 
     validationList.add("FILE8.txt"); 
    } 

    @Override 
    public List<String> getValidationList() { 
     return validationList; 
    } 
} 

Có ai biết làm thế nào tôi sẽ giải quyết createList gọi phương thức() hoặc createSecondList() - mà không sử dụng các nhà xây dựng có khá nhiều lực lượng thiết kế. Tôi đã nghĩ đến một nhà máy, nhưng một nhà máy cho mỗi lớp trong một dự án có độ lớn hơn không có vẻ như là một ý tưởng hay.

Cái gì như:

<bean ... factory-method="..." depends-on="..." lazy-init="..."/> 

Và trong phương pháp nhà máy nhanh chóng lớp và gọi phương thức createList(). Hoặc gọi nó như thế này, từ một số phương pháp - mà lại có vẻ xấu, buộc phương pháp có trách nhiệm khởi tạo biểu đồ đối tượng.

Những hình ảnh của sự phụ thuộc thời gian chạy mà tôi muốn giải quyết trong thời gian chạy là dưới đây:

enter image description here

Có một số cách khác mà tôi có thể sử dụng container để đạt được initalization lười biếng động tùy thuộc vào sự tương tác người dùng ?

Cảm ơn bạn.

+1

Tôi không biết bạn đang hỏi gì. Ý bạn là gì bởi "_solve_ phương thức gọi createList() hoặc createSecondList()"? Nếu tôi đoán đúng về những gì bạn đang cố gắng làm (và tôi nghi ngờ nó), tôi sẽ tạo một lớp nhà máy có phương thức nhà máy (tĩnh?) Lấy đối số tương tác và tạo danh sách thích hợp, sau đó tiêm một đối tượng nhà máy của lớp đó vào đối tượng chính của bạn. –

+0

Tôi nghĩ bạn sẽ hiểu được từ ngữ cảnh. Không phải là một nhà văn câu hỏi tuyệt vời. Vâng, một cái gì đó như thế này. Câu hỏi được in đậm. Bên cạnh nhà máy (tĩnh, tất nhiên) và sử dụng pull/initialization của các đối tượng (với khởi tạo trong lớp Main, "main" method), làm thế nào tôi có thể xây dựng đồ thị đối tượng động vì vậy tôi không phải lo lắng về kiến ​​trúc "mã "trong ứng dụng của tôi. Tại sao bạn sẽ tiêm đối tượng nhà máy trong đối tượng chính của bạn? Bạn sẽ có rất nhiều công việc nếu tất cả các lớp học của bạn đều năng động. Vì bạn nên có một nhà máy ở mọi tầng lớp năng động. Tôi vẫn tin rằng có một giải pháp đơn giản hơn :) – pfh

Trả lời

10

Nếu bạn muốn một số thành viên trong lớp của bạn được tự động khởi tạo \ populated trên mỗi cuộc gọi đến getter tương ứng, bạn có thể thử phương pháp tra cứu tiêm. Đọc Trang 3.3.4.1here.

Vì vậy, ngay cả khi lớp chứa thành viên động được tạo trong scope=singletone (mặc định cho vùng chứa đậu mùa xuân) mỗi lần bạn sẽ nhập trường có phương thức tra cứu được chỉ định, bạn sẽ nhận được đối tượng thích hợp theo logic nghiệp vụ được triển khai bên trong phương thức tra cứu. Trong trường hợp của bạn, danh sách là một giao diện để bạn có thể dễ dàng thực hiện xác thực trong phương thức tra cứu của mình và trả về một danh sách đã được xác nhận hợp lệ.

Edit:

tôi thấy tốt hơn example trong tài liệu Xuân - Tôi nghĩ rằng đó là rất rõ ràng. Hãy nhìn vào "3.4.6.1 Lookup phương pháp tiêm"

Khi bạn cấu hình các lớp Main gán một phương pháp tra cứu để thành viên List của nó - nó sẽ được gọi bất cứ khi nào bạn cần một ví dụ mới của bean List.

Chúc may mắn!

+0

Đó là một ý tưởng hay, nhưng việc di chuyển nhà máy thành một phương pháp dường như không giải quyết được mã lệnh. Ngoài ra, nó cho biết thêm sự phức tạp. Đột nhiên, phương thức phải trả về kiểu được yêu cầu. Và sau đó tôi có N phương pháp khi tôi yêu cầu N loại. Tôi có nhìn điều này sai không? Spring không có nội dung nào giống như @AssistedInject (http://code.google.com/p/google-guice/wiki/AssistedInject, https://jira.springsource.org/browse/SPR-5192)? Bạn có thường làm một cái gì đó như thế này nếu bạn có một ứng dụng "năng động"? Điều này có vẻ như một khu vực mà các lập trình viên có kinh nghiệm không truy cập thường xuyên ... – pfh

+0

Tôi nghĩ rằng một phương pháp tra cứu duy nhất là đủ (chắc chắn rằng bạn đã không bỏ lỡ điểm này) :) phương pháp tra cứu sẽ trả về một đối tượng thực hiện một số phổ biến giao diện (Danh sách?) hoặc thậm chí là một giao diện điểm đánh dấu. Quyết định về loại đối tượng chính xác mà phương pháp tra cứu sẽ sản xuất có thể dựa trên một số nguồn bên ngoài (tệp cấu hình, đầu vào người dùng, v.v.) nhưng tất cả các loại có thể cần phải được biết trước – aviad

+0

Tôi đang cố gắng không bỏ lỡ điểm, nhưng có vẻ như tôi thất bại. Đừng hiểu lầm tôi, tôi rất biết ơn câu trả lời. Điều này - http://java.dzone.com/articles/pragmatic-look-method là rất khác với những gì tôi muốn đạt được. Tôi đang cố gắng xem xét điều này từ tất cả các góc độ mà tôi có thể nghĩ đến ... Làm thế nào về bạn thực sự cố gắng làm một ví dụ và chứng minh điều này? Có, tôi có thể sử dụng giao diện điểm đánh dấu.Nhưng sau đó tôi "chỉ" phải giải quyết sự phụ thuộc thời gian chạy. Và "phương pháp tiêm" không thực sự giải quyết điều này. Làm thế nào tôi có thể nhanh chóng các đối tượng khác nhau tùy thuộc vào thời gian chạy? Tôi đã cập nhật câu hỏi của tôi để bạn có thể có một cái nhìn khác. – pfh

2

Âm thanh như người dùng có thể chọn 1 ..N đồ thị của các đối tượng và bạn chỉ muốn tải một cái mà người dùng chọn khi chạy. Nếu các đồ thị được biết tại thời điểm thiết kế nhưng người dùng chỉ chọn cái mà họ muốn thì nó nghe với tôi giống như những gì bạn có là một loạt các ApplicationContexts và bạn chỉ muốn tải một ApplicationContext mà người dùng chọn khi chạy. Vì vậy, tại sao không chỉ xác định tập hợp các ApplicationContexts và sau đó chỉ cần khởi tạo một tập hợp đúng lúc chạy. Vì Spring hỗ trợ Java Config nên bạn có thể định nghĩa các cấu hình này là các lớp Java để bạn có thể nhận được thừa kế và tránh cắt/dán bất kỳ mã nào.

+0

Chính xác. Nhưng vấn đề là container "không biết" các đối tượng trong thời gian chạy là gì. Nếu bạn có một Tệp và mong muốn người dùng chọn tệp đó, bạn không thể thực sự xác định trước tất cả các kết hợp có thể có. Ý tưởng là tốt, nhưng phần năng động được giải quyết (sử dụng danh sách như là một "toàn cầu" đậu). Vấn đề thực sự là làm thế nào để khởi tạo đối tượng KHI người dùng hành động (ví dụ: bấm vào một nút), biết rằng bạn có khởi tạo trong phương thức của mình. Tôi cần một số loại lười biếng, nhưng không muốn hy sinh mã sạch sẽ với các nhà máy hoặc phương pháp bẩm sinh theo phương pháp chính của tôi. – pfh

3

Mùa xuân được thiết kế để tiêm lại thành phần có thể sử dụng lại, không cho thao tác và thao tác dữ liệu nghiệp vụ.

Thật vậy, một số dữ liệu được sử dụng trong tiêm phụ thuộc, nhưng chỉ để cấu hình hành vi thành phần chứ không phải để tạo chủ dữ liệu nghiệp vụ.

Bằng cách này, các tùy chọn sau đây có thể được sử dụng trong trường hợp của bạn: cảm ơn BeanFactory với BeanFactoryAware interface và việc sử dụng các phạm vi = "nguyên mẫu", bạn có thể tạo một bean bằng cách gọi getBean() như trong that example hoặc từ that other question: creating bean on demand.

Một lựa chọn thay thế nếu bạn có một số hạn chế về đậu để chuẩn bị là sử dụng chung tạo đậu the same way lacking beans are mocked

Bây giờ xem xét rằng mùa xuân không bao giờ thu thập rác đậu trong bối cảnh của nó. Vì vậy, nó là nguy hiểm cho bộ nhớ tiêu thụ để tạo ra đậu mùa xuân để giữ dữ liệu kinh doanh.

Nếu mục tiêu của bạn là khác nhau (tôi hy vọng như vậy), có thể bạn đang cố gắng thực hiện bằng cách hỗ trợ nhiều người thuê nhà của riêng bạn. Spring cung cấp hợp đồng thuê nhà trong trường hợp bạn có ngữ cảnh kinh doanh khác nhau để triển khai với các thành phần hoặc hành vi cụ thể.

+0

Không, tôi, một lần nữa, đã cố gắng kết hợp dữ liệu và kiến ​​trúc kinh doanh. Vấn đề là, nếu bạn đang sử dụng kiến ​​trúc OOP, bạn không thể thực sự sử dụng vùng chứa cho nhiều lần tiêm. Nếu bạn bắt đầu sử dụng các dịch vụ không quốc tịch và chia mã thành các đối tượng dữ liệu và các dịch vụ, bạn có thể sử dụng rất nhiều. Nhưng tôi không cho điều đó. Tôi nghĩ rằng các đối tượng statefull vẫn cai trị (đó là quan điểm của tôi). Tôi hiểu bộ sưu tập rác, đối tượng là một singleton, sẽ không có bất kỳ vấn đề gì. Sự gia tăng bộ nhớ nhỏ là hầu như invisibile. Vấn đề vẫn còn - bạn không thể "cắt" mã thành mã arhitecture visibile. – pfh

+0

OK cho thành phần statefull với dữ liệu nghiệp vụ được nhúng. Nhưng làm thế nào xử lý đồng thời hoặc truy cập nhiều người dùng nếu nó chỉ là một singleton. Bạn sẽ sử dụng các biến thread-local bên trong một singleton? Bạn sẽ chuyển sang mẫu nhà máy? Các khái niệm JavaEE chân thành đã được thiết kế xung quanh các mẫu có tính an toàn và có thể mở rộng. Mùa xuân đã được thiết kế để sử dụng cùng một mẫu theo cách nhẹ hơn nhưng mục tiêu vẫn là: đồng thời cho hiệu suất. –

+0

"Làm cho nó hoạt động, sau đó tối ưu hóa". Mục tiêu không phải là để đối phó với đồng thời ngay bây giờ, ý tưởng là để đến với một cách để sử dụng một container trong một môi trường năng động.Đối phó với các lớp statefull vẫn là một vấn đề khi sử dụng một số loại container trong một ứng dụng. Bỏ qua một bên, ý tưởng của bạn để đối phó với nó là khá tốt. Và mục tiêu "đồng thời cho hiệu suất" không thực sự là một điều mới. Vì vậy, có, bạn có thể làm cho nó hoạt động bằng cách sử dụng một singleton cho mỗi người dùng (bạn có thể tranh luận rằng đó sẽ không phải là một singleton). Nhưng để đạt được một container thực sự tuyệt vời có nghĩa là để làm cho nó năng động. – pfh

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