bây giờ mình sẻ phân tích ví dụ này

13
Bây giờ mình sẻ phân tích ví dụ này. Trước hết chúng ta hảy xem hàm main trong class App Code: (Click Here to Select All) public static void main(String[] args){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); XeMay xehaiky = (XeMay) context.getBean("xebonky"); XeMay xebonky = (XeMay) context.getBean("xehaiky"); System.out.println(xehaiky.XeNoMay()); System.out.println(xebonky.XeNoMay()); } Đáng ra nếu bình thường thì chúng ta thường viết như sau : Code: (Click Here to Select All) public static void main2(String[] args){ DongCo dongcohaiky = new DongCoHaiKy(); DongCo dongcobonky = new DongCoBonKy(); XeMay xehaiky = new XeMay(dongcohaiky); XeMay xebonky = new XeMay(dongcobonky);

Upload: thuy2011ptit

Post on 22-Apr-2015

99 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Bây giờ mình sẻ phân tích ví dụ này

Bây giờ mình sẻ phân tích ví dụ này.

Trước hết chúng ta hảy xem hàm main trong class AppCode: (Click Here to Select All)

public static void main(String[] args){

ApplicationContext context =

new ClassPathXmlApplicationContext("beans.xml");

XeMay xehaiky = (XeMay) context.getBean("xebonky");

XeMay xebonky = (XeMay) context.getBean("xehaiky");

System.out.println(xehaiky.XeNoMay());

System.out.println(xebonky.XeNoMay());

}

Đáng ra nếu bình thường thì chúng ta thường viết như sau :Code: (Click Here to Select All)

public static void main2(String[] args){

DongCo dongcohaiky = new DongCoHaiKy();

DongCo dongcobonky = new DongCoBonKy();

XeMay xehaiky = new XeMay(dongcohaiky);

XeMay xebonky = new XeMay(dongcobonky);

System.out.println(xehaiky.XeNoMay());

System.out.println(xebonky.XeNoMay());

Page 2: Bây giờ mình sẻ phân tích ví dụ này

}

So sánh ta có thể thấy ở đây trong hàm main chúng ta không cần dùng toán tử new để khởi tạo các đối tượng xehaiky và xebonky. Chúng ta củng không phải tạo các đối tượng động cơ để truyền vào cho các đối tượng của class XeMay. Vậy thì - ai đả tạo ra các đối tượng xehaiky, xebonky?- Và chúng lấy các đối tượng DongCo từ đâu ?- Và file beans.xml có ý nghĩa và vai trò như thế nào?Trước khi trả lời nhửng câu hỏi này mình muốn nhắc lại ở phần giới thiệu về IoC và DI mình đả nói là dùng IoC để thay đổi trách nhiệm tạo ra đối tượng “dongco” của class XeMay cho một thành phần nào đó bên ngoài. Trong bài helloworld này thành phần bên ngoài đả tạo ra các đối tượng xemayhaiky, xemaybonky và các đối tượng DongCo là các thành phần của spring framework mà chúng ta đả sử dụng(đó là IoC container).

Trong Spring các đối tượng chính để xây dựng ứng dụng thì được quản lý bởi Spring IoC container. Và IoC container gọi các đối tượng đó là các bean. Một bean chỉ đơn giản là một đối tượng được khởi tạo và quản lý bởi Spring IoC container.

Ta đả biết là giữa các bean thì có sự phụ thuộc lẩn nhau vậy làm sao Spring Framework biết được chúng phụ thuộc lẩn nhau như thế nào ? Làm sao biết được cần tạo ra đối tượng nào, truyền các loại DongCo vào các đối tượng của class XeMay ra sao , … Spring sử dụng hai cách( hai loại metadata) để người lập trình có thể cấu hình các bean (tạo ra như thế nào, phụ thuộc vào ai , …) đó là dùng Annotation( Java 5 mới hổ trợ Annotation) và file XML . Trong ví dụ này mình đả sử dụng file beans.xml để cấu hình các bean. Trước khi phân tích file beans.xml nếu bạn nào chưa biết về xml thì có thể tham khảo tại đây :http://vi.wikipedia.org/wiki/XML.File beans.xml : Code: (Click Here to Select All)

<?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.xsd">

<bean id="dongcohaiky" class="example.com.DongCoHaiKy"></bean>

<bean id="dongcobonky" class="example.com.DongCoBonKy"></bean>

Page 3: Bây giờ mình sẻ phân tích ví dụ này

<bean id="xehaiky" class="example.com.XeMay">

<constructor-arg name="dongco" ref="dongcohaiky"></constructor-arg>

</bean>

<bean id="xebonky" class="example.com.XeMay">

<constructor-arg ref="dongcobonky"></constructor-arg>

</bean>

</beans>

Trước hết là phần tử beans đây là phần tử root của file xml. Nó sẽ chứa tất cả các phần tử bean của chúng ta và ngoài ra nó còn có một số thuộc tính nhưng trong khuôn khổ bài này mình nghĩ rằng chúng ta không phải quan tâm đến chúng.Bây giờ chúng ta sẽ xét tới phần tử bean.

Code: (Click Here to Select All)

<bean id="dongcohaiky" class="example.com.DongCoHaiKy"></bean>

Với phần tử bean này chúng ta sẽ cấu hình cho IoC container tạo ra một bean của class "example.com.DongCoHaiKy". Ta thấy phần tử này có hai thuộc tính “id” và “class”. Thuộc tính “id” được dùng để định danh. Một bean có thể có nhiều id, nhưng các id không được trùng nhau.Còn thuộc tính “class” là dùng để chỉ bean đó được tạo thành từ class nào.Nhưng với phần tử bean này nó lại có phần tử con :Code: (Click Here to Select All)

<bean id="xehaiky" class="example.com.XeMay">

<constructor-arg name="dongco" ref="dongcohaiky"></constructor-arg>

</bean>

Trong ví dụ mình đả đưa ra thì constructor của class XeMay có một đối số truyền vào. Và phần tử con <constructor-arg> dùng để cấu hình cho IoC container biết là phải truyền đối số nào vào cho constructer của class XeMay. Ta thấy phần tử <constructor-arg > có thuộc tính “ref = “dongcohaiky” ” cấu hình cho IoC container biết được là truyền bean nào vào cho contructer của class XeMay. Giá trị của thuộc tính ref là id của bean mà chúng ta muốn truyền vào.Bây giờ chúng ta hảy xem lại hàm main, dòng đầu tiên là :Code: (Click Here to Select All)

ApplicationContext context =

Page 4: Bây giờ mình sẻ phân tích ví dụ này

new ClassPathXmlApplicationContext("beans.xml");

Dòng này dùng để khởi tạo IoC container với phần cấu hình là file beans.xml. Và đối tượng context là đại diện cho container đó, nó có trách nhiệm khởi tạo, cấu hình các đối tượng và quản lý sự phuc thuộc giữa các đối tượng trong container.

Bạn có thể hình dung IoC container theo hình trên.Code: (Click Here to Select All)

XeMay xehaiky = (XeMay) context.getBean("xebonky");

Ở đây ta dùng phương thức “getBean()” của ApplicationContext interface để truy cập bean có id =”xebonky” mà chúng ta đả cấu hình trong file beans. Xml

Để cấu hình các bean thì bạn sẻ phải sử dụng phần tử <bean></bean> trong file xml. Với phần tử này thì các bạn sẻ làm việc với các vấn đề sau :• Namimg beans.• Instantiating beans.• Bean scopes.• Dependency injection• Autowiring collaboratiors.• Lazy-initialized beans.• Initialization callbacks.• Destruction callbacks.

Chúng ta sẽ từng bước làm việc với các vấn đề này.

Naming beans:

Để beans container có thể quản lý được các bean thì chúng phải có cá định danh (giống như con người phải có tên vậy). Spring cho phép chúng ta có thể đặt cho bean một định danh hoặc có thể là nhiều định danh. Chúng ta cấu hình trên file xml thì chúng ta có thể dùng hai thuộc tính là “id

Page 5: Bây giờ mình sẻ phân tích ví dụ này

“ và “name” để đặt định danh cho bean. Nếu chúng ta sử dụng id thì nó phải là duy nhất trong trong bean container. Khi bạn muốn nhiều định danh cho một bean bạn có thể dùng thuộc tính name và các định danh với name có thể cách nhau bằng khoảng trắng, dấu phẩy hoặc dấu chấm phẩy. Nếu bạn không tự định danh cho bean thì bean container sẻ tự sinh ra cho bean đó một định danh.Với hai cách định danh trên thì các thuộc tính thuộc phần tử <bean>. Bạn có thể thêm định danh cho bean bằng cách dùng alias. Bạn có thể dùng phần tử <alias> để thêm định danh cho bean. Để dễ hiểu hơn bây giờ mình sẻ lấy một ví dụ về định danh cho bean:

File: context.xml

Code: (Click Here to Select All)

<?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.xsd">

<bean id="name1" name="name2,name3,name4" class="java.lang.String"/>

<alias name="name1" alias="namex1"/>

<alias name="name1" alias="namex2"/>

</beans>

File: Main.java

Code: (Click Here to Select All)

import org.springframework.beans.factory.BeanFactory;

import org.springframework.beans.factory.xml.XmlBeanFactory;

import org.springframework.core.io.ClassPathResource;

Page 6: Bây giờ mình sẻ phân tích ví dụ này

public class Main {

public static void main(String[] a) {

BeanFactory factory = new XmlBeanFactory(new ClassPathResource("context.xml"));

String s1 = (String) factory.getBean("name1");

String s2 = (String) factory.getBean("name2");

String s3 = (String) factory.getBean("name3");

String s4 = (String) factory.getBean("name4");

String s5 = (String) factory.getBean("namex1");

String s6 = (String) factory.getBean("namex2");

System.out.println((s1 == s2));

System.out.println((s2 == s3));

System.out.println((s3 == s4));

System.out.println((s4 == s5));

System.out.println((s5 == s6));

}

}

Qua ví dụ vừa rồi các bạn có thể hiểu được cú pháp để đặt định danh cho bean.

Khi container tạo một bean thì làm sao nó biết được là cần tạo bean của class nào. Với XML thì chúng ta sử dụng thuộc tính “class” trong phần tử <bean>. Như chúng ta đả biết trong lập trình java có hai cách để chúng ta tạo ra đối tượng. Cách thứ nhất là dùng toán tử new ( thông qua constructor). Cách thứ hai là dùng hàm static của một class nào đó(thường là một Factory). Ví dụ như :

XeMay xemay = new XeMay(); // qua constructorXeMay xemay = HonDa.createXeMay(); //qua static method là createXeMay().

Page 7: Bây giờ mình sẻ phân tích ví dụ này

Và spring củng hổ trợ chúng ta hai cách để tạo ra bean bằng constructor và static method.

Khởi tạo bằng constructor:Code: (Click Here to Select All)

<bean id="exampleBean" class="examples.ExampleBean"/>

<bean name="anotherExample" class="examples.ExampleBeanTwo"/>

Như ví dụ thì thuộc tính class được gán bằng tên của class mà nó muốn tạo bean.Khởi tạo bằng static method :

Giả sử ta có class sau :

Code: (Click Here to Select All)

public class ClientService {

private static ClientService clientService = new ClientService();

private ClientService() {}

public static ClientService createInstance() {

return clientService;

}

}

Và để khởi tạo đối tượng cho class đó thì ta phải cấu hình như sau :

Code: (Click Here to Select All)

<bean id="clientService" class="examples.ClientService" factory-method="createInstance"/>

Khi đó thuộc tính class sẻ được gán bằng tên của Class có phương thức static như ví dụ trên.Nhưng khi mà khởi tạo một đối tượng (bean) từ một đối tượng (bean) khác thì sao. Spring làm như ví dụ sau :Code: (Click Here to Select All)

public class DefaultServiceLocator {

private static ClientService clientService = new ClientServiceImpl();

private DefaultServiceLocator() {}

public ClientService createClientServiceInstance() {

Page 8: Bây giờ mình sẻ phân tích ví dụ này

return clientService;

}

}

Code: (Click Here to Select All)

<!-- the factory bean, which contains a method called createInstance() -->

<bean id="serviceLocator" class="examples.DefaultServiceLocator">

<!-- inject any dependencies required by this locator bean -->

</bean>

<!-- the bean to be created via the factory bean -->

<bean id="clientService" factory-bean="serviceLocator" factory-method = "createClientServiceInstance"/>

bean scope.

Khi bạn cấu hình một bean, và bean container sẻ tạo đối tượng(bean) cho bạn.Bạn sẻ muốn bean container tạo cho bạn mấy đối tượng như vậy, hay là chỉ cần tạo một đối tượng thôi thôi ,… Và để cấu hình việc này bạn phải sử dụng thuộc tính scope. Scope sẻ có nhửng giá trị sau :

Singleton : Với mổi bean container chỉ tao duy nhất một đối tượng Prototype: tạo một đối tượng mới khi có yêu cầu Request : tạo một đối tượng cho mổi lần có HTTP request. Session : tạo một đối tượng cho mổi HTTP session. globalSession : tạo một đối tượng cho một global HTTP session.

Trong phạm vi bài này mình chỉ muốn giới thiệu đến Singleton và Prototype. Vì đây là hai giá trị thường được dùng nhât. Còn ba thuộc tính còn lại chỉ sử dụng trong ứng dụng web. Và giá trị mặc định của scope là singleton.Scope = “singleton” nghỉa là trong một bean container chỉ tạo ra một đối tượng duy nhất của bean đó. Để dễ hiểu chúng ta lấy ví dụ như sau :File CustomerService.java

Code: (Click Here to Select All)

package com.example;

public class CustomerService

{

Page 9: Bây giờ mình sẻ phân tích ví dụ này

String message;

public String getMessage() {

return message;

}

public void setMessage(String message) {

this.message = message;

}

}

File cấu hình beans.xml:Code: (Click Here to Select All)

<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-2.5.xsd">

<bean id="customerService"

class="com.example.CustomerService" scope="singleton" />

</beans>

File App.javaCode: (Click Here to Select All)

package com.example;

import org.springframework.context.ApplicationContext;

Page 10: Bây giờ mình sẻ phân tích ví dụ này

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.example.CustomerService;

public class App

{

public static void main( String[] args )

{

ApplicationContext context =

new ClassPathXmlApplicationContext(new String[] {"beans.xml"});

CustomerService custA = (CustomerService)context.getBean("customerService");

custA.setMessage("Message by custA");

System.out.println("Message : " + custA.getMessage());

CustomerService custB = (CustomerService)context.getBean("customerService");

System.out.println("Message : " + custB.getMessage());

}

}

Khi chúng ta chạy ứng dụng này thì kết quả thu được sẻ là :Code: (Click Here to Select All)

Message : Message by custA

Message : Message by custA

Như bạn có thể thấy ở đây khi chúng ta yều cầu bean container hai lần nhưng chỉ có một đối tượng được tạo ra.

Page 11: Bây giờ mình sẻ phân tích ví dụ này

Còn với scope=”prototype” thì mổi lần chúng ta yêu cầu bean container sẻ tạo cho chúng ta một đối tượng mới. Và với ví dụ trên nếu chúng ta thay đổi scope = “prototype” như sau :

File beans.xml

Code: (Click Here to Select All)

<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-2.5.xsd">

<bean id="customerService" class="com.mkyong.customer.services.CustomerService"

scope="prototype"/>

</beans>

Khi đó kết quả thu được sẻ là :Code: (Click Here to Select All)

Message : Message by custA

Message : null

Như vậy với cách cấu hình thứ hai thì mổi lần chúng ta gọi phương thức getBean(“”) thì bean container phải tạo một đối tượng mới.