2013-02-27 36 views
12

Tôi chỉ mới bắt đầu với khái niệm Spring IOC. Tôi thường thấy hầu hết các ví dụ được tìm thấy trên internet sử dụng mã để lấy đối tượng.Cách tránh sử dụng ApplicationContext.getBean() khi triển khai Spring IOC

ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml"); 
Hello hello = (Hello) appContext.getBean("hello"); 

Là một tài liệu tham khảo từ những câu hỏi 12 trong stackoverflow. Tôi đã suy ra rằng, không cần thiết phải sử dụng appContext.getBean ("hello") trong mã được coi là thực hành không tốt. Ngoài ra, không được khuyến khích nữa. Đúng tôi ở đây, Nếu suy luận của tôi là sai.

Theo quan điểm đó, tôi đã thực hiện các thay đổi trong dự án của mình cho phù hợp. Dưới đây là applicationContext.xml tôi

<?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.2.xsd"> 
<bean id="utilClassRef" class="org.hd.derbyops.DUtils" lazy-init="false" /> 
<bean id="appContext" class="org.hd.derbyops.ContextProvider" lazy-init="false"> 
    <property name="utils" ref="utilClassRef" /> 
</bean> 
</beans> 

My contextProvider Lớp Mã

public class ContextProvider implements ApplicationContextAware { 

    private static ApplicationContext ctx; 

    /** 
    * Objects as properties 
    */ 
    private static DUtils utils; 

    public void setApplicationContext(ApplicationContext appContext) 
      throws BeansException { 
     ctx = appContext; 

    } 

    public static ApplicationContext getApplicationContext() { 
     return ctx; 
    } 

    public static DUtils getUtils() { 
     return utils; 
    } 

    public void setUtils(DUtils dUtilsRef) { 
     utils = dUtilsRef; 
    } 

} 

Ví dụ, hãy xem xét một lớp Một mà phụ thuộc vào org.hd.derbyops.DUtils. Tôi đang sử dụng các dòng mã sau

ContextProvider.getUtils(); 

inorder để có được DUtils Object trong lớp A, như vậy tránh được việc sử dụng của ApplicationContext.getBean() bất cứ nơi nào trong mã của tôi.

Giả sử, nếu tôi có 10 lớp và lớp A của tôi phụ thuộc vào tất cả các lớp, đối tượng của chúng sẽ được tạo và truy cập mà không cần sử dụng ApplicationContext.getBean(). Trong trường hợp đó cũng vậy, như đã thực hiện ở trên, tôi có một ý nghĩ về việc tạo các thuộc tính của lớp ContextProvider theo sau bởi setter và getter của thuộc tính đó, trong đó trong get<PropertyName> là tĩnh. Vì vậy, tôi có thể sử dụng nó bất cứ nơi nào tôi cần một đối tượng, như thế này

ContextProvider.get<PropertyName>; 

Đây là câu hỏi ngắn gọn của tôi. Thứ nhất, cách tiếp cận của tôi có đúng không? Nếu nó đúng, tải tất cả các hạt lúc khởi động, nó sẽ không phải là một kẻ giết người hiệu suất? Làm thế nào bạn sẽ làm điều đó trong các ứng dụng của bạn mà không gọi getBean ít nhất một lần?

Nếu bạn đã thiết kế một ứng dụng web &, bạn đã triển khai Spring IOC, mà không cần sử dụng ApplicationContext.getBean() trong bất kỳ mã nào. Bạn làm điều đó như thế nào?

Lưu ý: có sự tham khảo các câu hỏi khác được gắn thẻ trên

Calling ApplicationContext.getBean() không phải là Inversion of Control!

+0

Bạn đang sử dụng Spring MVC hoặc cố gắng sử dụng các servlet cơ bản? –

+0

Tôi không sử dụng Spring MVC, chỉ cần sử dụng nó cho IOC – srk

+2

Nói chung, * ai đó * sẽ cần lấy một bean từ 'ApplicationContext'. Lý tưởng nhất, nó chỉ được gọi là một lần, và nó sẽ là bởi đối tượng bootstrapping ... –

Trả lời

9

Câu trả lời đơn giản là có và không, không và không. Và cuối cùng, thực hiện tìm kiếm trực tuyến cho mùa xuân MVC, vì điều này có thể làm những gì bạn muốn.

Vì vậy, cách tiếp cận của bạn. Có, bạn đã có hầu hết nó đúng. Tuy nhiên, nó được coi là thực hành rất xấu để sử dụng phương pháp tĩnh cho tất cả mọi thứ. Và, bạn không cần phải. Mùa xuân dựa trên ý tưởng rằng bạn có thể tạo pojos bình thường, và mùa xuân sẽ sử dụng chúng như những người độc thân, và tiêm chúng vào nhau (nó cũng có thể tạo ra các vật thể trên bay, nhưng tôi sẽ cho trường hợp phổ biến ở đây). Nếu bạn sử dụng các lớp và phương pháp tĩnh thì:

  • Bạn không thể thử chúng để thử nghiệm đơn vị (bạn đang sử dụng JUnit phải không?)
  • Bạn không thể sử dụng chúng với thừa kế
  • initialisers tĩnh là một cách tuyệt vời để mất ngoại lệ
  • vv, vv

Vì vậy, có cho tiêm, và không để những thứ tĩnh.

Tiếp theo, hiệu suất. Bạn đang ở ngay trong đó nó là rất nhiều chậm hơn để sử dụng mùa xuân, nhưng, nếu bạn làm tất cả các tiêm của bạn khi khởi động nó chỉ xảy ra một lần. Mùa xuân có nghĩa là cho các ứng dụng phía máy chủ, nơi có khả năng là một số lớp singleton truyền dữ liệu xung quanh. Vì vậy, có thể có một lớp học để có được công cụ từ một DB, một để xử lý nó, và một để hiển thị nó, và mùa xuân được sử dụng để dây chúng lại với nhau.

Nếu bạn đang sử dụng ứng dụng trong đó bạn bắt đầu liên tục, như ứng dụng dòng lệnh, thì bạn đang sử dụng ứng dụng sai loại và có thể bạn muốn sử dụng trình tạo hoặc một thứ gì đó. Mùa xuân có nghĩa là cho các ứng dụng doanh nghiệp lớn không được khởi động lại thường xuyên.

Cuối cùng, nếu bạn chỉ cần tiêm tất cả các phụ thuộc cho một lớp vào lúc khởi động, và bạn làm điều này với tất cả các lớp của bạn, thì bạn không cần phải làm bất kỳ công cụ getBean nào cả. Ngoài ra, sử dụng thuộc tính init-methoddestroy-method trên bean có nghĩa là bạn có thể bắt đầu các quy trình sau khi mùa xuân đã hoàn tất việc tiêm phụ thuộc. Bạn chỉ cần tải ngữ cảnh và ứng dụng của bạn sẽ phát hành (có ý định chơi chữ) thành sự tồn tại.

Đối với các dự án web, Spring MVC về cơ bản mất toàn bộ mẫu điều khiển và áp dụng cho các ứng dụng web. Các công cụ mùa xuân được nạp bởi vùng chứa và bạn có thể xác định các URL để phản hồi bằng cách sử dụng không có gì hơn tên bean. Và hầu hết mã của bạn có thể ở dạng pojos. Nếu bạn có cái gì đó cực kỳ phức tạp, bạn có thể muốn xem xét luồng web mùa xuân, nhưng tôi khuyên bạn nên chắc chắn rằng foo mùa xuân của bạn rất mạnh trước khi thử điều đó.

+0

Trong mycompany, tôi chưa bao giờ thấy 'ApplicationContext.getBean()' và các công cụ. Nhưng đó là bởi vì đây là những ứng dụng web cấp doanh nghiệp. Vì vậy, những gì chính xác tải lên tất cả các lớp học của tôi cho tôi? Nó có phải là máy chủ không? – Kraken

+0

Thông thường, bạn sử dụng một trong các lớp tải ứng dụng Spring được đóng trước, đó là các thành phần JEE chuẩn như servlet và whatnot. Những điều này sau đó khởi động tất cả các công cụ IOC mùa xuân. Ẩn trong ruột của các lớp đó, sẽ có một cuộc gọi để tạo ngữ cảnh ứng dụng từ tệp XML, liên kết nó với ứng dụng hiện đang chạy và làm cho ngữ cảnh ứng dụng có sẵn theo một cách nào đó. – Jimadilo

1

Đây là ví dụ của tôi để nhận ví dụ đầu tiên mà không thực sự gọi số getBean() trên ApplicationContext.

public class Test{ 
    // Declare private static variable so that we can access it in main() 
    private static Triangle triangle; 

    // Use constructor injection to set the triangle 
    public Test(Triangle triangle) { 
     Test.triangle = triangle; 
    } 

    public static void main(String[] args) { 
     // Specify the context file containing the bean definitions 
     // Spring automatically creates instances of all the beans defined 
     // in this XML file. This process is performed before you actually make 
     // a getBean("beanName") call. 
     ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); 

     // Use instance methods of triangle 
     Test.triangle.draw(); 
    } 
} 

Bạn có thể dùng một cách khác:

Trong spring.xml (đậu của bạn tập tin cấu hình XML)

<bean class="com.example.Test" init-method="myMethod"> 
    <constructor-args ref="triangle"/> 
</bean> 

Bây giờ cho lớp học chính của bạn

public class Test { 
    private final Triangle triangle; 

    public Test (Triangle triangle) { 
    this.triangle = triangle; 
    } 

    public static void main (String[] args) { 
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); 
    } 

    // Called by Spring immediately after the Triangle Bean has been created and 
    // all the properties for the bean have been set. This method name must match 
    // the one specified with destroy-method attribute in spring.xml 
    public void myMethod() { 
    triangle.draw(); 
    } 
} 
Các vấn đề liên quan