Thứ Sáu, 3 tháng 6, 2011

Spring Framkework

Spring là tên gọi của một framework mới nổi trong thời gian gần đây. Có rất nhiều cách định nghĩa giải thích về Spring nhưng việc hiểu biết về Spring thì phụ thuộc nhiều vào trình độ, kinh nghiệm của người tìm hiểu. Nếu bạn hiểu biết càng nhiều về Java và J2EE thì bạn càng dễ dàng tiếp cận với Spring. Nói như vậy để thấy rằng việc đòi hỏi có một định nghĩa thật chính xác và dễ hiểu về Spring là việc không đơn giản.

Không nên nghĩ đơn giản rằng đọc một bài báo hay vài trang sách là thấu suốt mọi chuyện cũng không nên coi Spring là cái gì đó cao siêu quá. Tất cả đều bắt đầu rất logic và dễ hiểu.

Spring bắt nguồn từ J2EE với mong muốn làm đơn giản hóa các phức tạp nhiều khi không cần thiết của J2EE. Do bắt nguồn từ J2EE nên nếu bạn chưa biết gì về J2EE thì sẽ khó tiếp cận với Spring đúng không nào.

Các giải thích trước nay về Spring đều được dẫn dắt từ J2EE cho nên nó trở nên khó hiểu với độc giả chưa biết về J2EE. Sự khó hiểu của Spring còn bởi nó đề cập đến vô số khái niệm mà đa số chưa có thuật ngữ tiếng Việt tương ứng như: container (thùng chứa), business layer, persistent layer, IOC - Inversion of Control (Sự đảo ngược điều khiển), Injection Dependency (Sự phụ thuộc được tiêm vào từ bên ngoài chứ không do các đối tượng tự tạo ra)
)..

Vậy thì cách nào để tiếp cận dễ nhất với Spring?

Mọi lý thuyết đều vô nghĩa nếu như bạn chưa tự tay chạy thử một ví dụ về Spring

Các bước tiến hành

1. Download file spring jar, file chứa toàn bộ spring framework tại địa chỉ http://www.springframework.org/download.

2. Bây giờ viết 1 chương trình hello spring theo cách bước sau:
Tạo thư mục SpringExample
Tạo một project tên SpringExample nằm tại thư mục trên
Tạo lớp tên Speaker (nôm na là cái loa có một phương thức là sayHello) nằm tại thư mục SpringExample cho đơn giản

//Bat dau lop

import java.io.FileInputStream;
import java.io.InputStream;

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


public class Speaker{

public void sayHello(){

System.out.println("Hello Spring");

}

//cài đặt một hàm main ngay trong lớp này để test cho nhanh

public static void main( String args[]) throws Exception{

InputStream is = new FileInputStream("beans.xml");

BeanFactory factory = new XmlBeanFactory(is);

Speaker speaker = (Speaker)factory.getBean("Speaker");

speaker.sayHello();

}
}

//ket thuc lớp

Trong hàm main chúng ta có truy cập đến 1 file tên là beans.xml. Đây là file rất quan trọng đối với ứng dụng chạy trên Srping. Nó chứa các thông tin về cấu hình của các bean được dùng trong ứng dụng của bạn.

Bây giờ bạn tạo file beans.xml nằm cùng với file java của lớp Speaker với nội dung như sau

//beans.xml


http://www.springframework.org/dtd/spring-beans.dtd">






Bây giờ thử chạy xem bạn sẽ thấy dòng chữ Hello Spring được in ra.

Mặc dù là một ví dụ đơn giản nhưng cũng giúp bạn hình dung phần nào về Spring. Nó sẽ giúp ích rất nhiều cho bạn khi đi vào các khái niệm khá phức tạp của Spring sau này.

Như bạn đã thấy trong hàm main, việc khởi tạo đối tượng Speaker từ lớp Speaker không làm theo cách truyền thống nghĩa là

Speaker speaker = new Speaker ();

Thay vào đó, speaker được tạo thành bằng cách

Speaker speaker = (Speaker)factory.getBean("Speaker");

Trong đó, factory là một đối tượng của lớp BeanFactory (Spring có hơn một ngàn lớp/interface như vậy) có tác dụng như một nhà máy sản xuất (tạo ra) các đối tượng khi người dùng đưa các yêu cầu vào, ở trường hợp này người dùng đã yêu cầu factory tạo ra 1 đối tượng từ mẫu có tên là Speaker.


FAQ

Tôi đã xem qua ví dụ trên vậy thì IoC (inversion of control, sự đảo ngược của điều khiển) mà mọi người hay nhắc tới như là nguyên lý nền tảng của Spring nằm ở chỗ nào? Đảo ngược điều khiển là đảo ngược cái gì và đảo ngược như thế nào? Nó có gì hay không? Còn Injection Dependency (việc tiêm sự phụ thuộc vào từ bên ngoài) là gì?

Các câu hỏi này sẽ trả lời bằng 1 ví dụ minh họa trong bài tới.
----------------------------------------
Tập tin đính kèm commons-logging-1.0.3.jar (31605 bytes) (Số lần tải về: 208)

Cái gì là nguyên lý nền tảng của Spring?


Trong ví dụ rất đơn giản của bài trước, lớp Speaker có một phương thức sayHello dùng để in ra câu Hello Spring. Ta sẽ mở rộng ví dụ này ra giải thích khái niệm IoC. Mặc dù đã cố găng hết sức đơn giản hóa ví dụ nhưng nó vẫn còn tương đối phức tạp (vì ứng dụng phải phức tạp mới phải dùng đến Spring mà!).

Tuy nhiên, bản chất của nó chỉ đơn giản là khi 2 đối tượng có sự phụ thuộc lẫn nhau (ví dụ đối tượng A là một thuộc tính của đối tượng B) thì cách chương trình giải quyết sự phụ thuộc này như thế nào mà thôi.

Bây giờ, giả sử các cái loa trước khi sayHello thì cần phải đi qua một bộ phiên dịch Translator. Ta sẽ viết lớp Translator có một phương thức traslate in ra dòng chữ Hello. Để lớp này có thể in ra được nhiều thứ tiếng ta sẽ viết dưới dạng 1 interface

public interface Translator {

public void translate();

}

Sau đó viết lớp EnglishTranslator để hiện thực interface này:

public class EnglishTranslator implements Translator{

public void translate(){

System.out.println("Hello Spring");

}
}


Ta thêm vào lớp Speaker thêm một thuộc tính gọi là translator

//Bat dau lop

import java.io.FileInputStream;
import java.io.InputStream;

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


public class Speaker{

private Translator translator;

public Speaker(Translator translator) {

this.translator = translator;

}

public void sayHello(){

translator.translate();

}

//ham main viet luon trong lop Speaker de test cho nhanh. Khong su dung Spring de tao doi tuong bang factory nua ma tao bang tay de so sanh su khac biet

public static void main( String args[]) throws Exception{

Translator translator = new EnglishTranslator();

Speaker speaker = new Speaker (translator);

speaker.sayHello();

}
}

//ket thuc lớp Speaker

Chạy thử xem có in được câu Hello Spring không

Nếu không thích in ra câu Hello ta có thể viết thêm hàm VietnameseTranslator

public class VietnameseTranslator implements Translator{

public void translate(){

System.out.println("Xin chao Spring");

}
}

Để in ra đuợc tiếng Việt ta phải chỉnh lại hàm main một chút. Thay vì viết

Translator translator = new EnglishTranslator();

ta viết

Translator translator = new VietnameseTranslator();

Như vậy rõ ràng sự bất tiện xuất hiện mỗi khi ta muốn thay đổi qua lại giữa tiếng Anh và tiếng Việt. Sự phụ thuộc giữa đối tượng thuộc lớp Speaker và Translator được giải quyết trong chương trình nghĩa là khi nào muốn tiếng Việt thì ta chỉnh lại đoạn code một ít. Sự điều khiển (control) phụ thuộc (dependency) giữa các đối tượng do chương trình đảm trách. Nó là cách thông thường ta vẫn làm. Gọi là sự điều khiển bình thường.

Bây giờ ta sửa lại hàm main để sử dụng Spring

public static void main( String args[]) throws Exception{

InputStream is = new FileInputStream("beans.xml");

BeanFactory factory = new XmlBeanFactory(is);

Speaker speaker = (Speaker)factory.getBean("Speaker");

speaker.sayHello();

}

Ta thấy hàm main bây giờ không dính dáng gì đến Vietnamese và English nữa.

Và sửa lại file beans.xml


http://www.springframework.org/dtd/spring-beans.dtd">













File beans.xml bây giờ đảm nhận việc lắp ráp EnglishTranslator hoặc là VietnameseTranslator. Sự điều khiển (control) đã được đảo ngược (inversion) sang cho BeanFactory đảm trách. Hay nói cách khác Spring đã tiêm đối tượng EnglishTranslator (hoặc là VietnameseTransslator) vào trong đối tượng Speaker (Injection Dependency).

Đó là nguyên lý chính yếu nhất, nổi tiếng nhất của Spring.

FAQ

Lập trình theo khía cạnh (Aspect oriented programming) là gì? Nó liên quan gì đến Spring?

Spring dính dáng gì đến framework nổi tiếng nhất của Java J2EE?

Sping là J2EE được đơn giản hóa cho nên nó giữ nguyên các nguyên lý thiết kế của J2EE (MVC - Module View Controler gọi nôm na là 3 lớp, Transaction, Persistence, Remoting...). Thật vậy, Spring ra đời khi Rod Johnson viết cuốn sách lừng danh Expert One-on-One J2EE Development without EJB (khoảng 1000 trang, bán tại Amazon giá khoảng 27 đô http://www.amazon.com/exec/obidos/tg/detail/-...3909193-5919055?v=glance)

nghĩa là dùng Spring có thể viết các ứng dụng J2EE mà không phải dùng đến EJB làm chi cho rắc rối.

Spring đóng vai trò là tầng (không nên dùng từ lớp bởi vì dễ nhầm với class) business (thường gọi là tầng nghiệp vụ) nằm giữa tầng GUI (giao diện người dùng) và tầng database (còn gọi persistence). Triết lý mô hình 3 lớp là tầng GUI không truy cập trực tiếp xuống database mà sẽ truy cập thông qua tầng business (tầng trung gian mà).

Tại sao 3 lớp hay hơn 2 lớp?
Có rất nhiều lập luận chứng minh điều này (dài dòng và kinh viện1!) nhưng để cho dễ thuyết phục thì cứ lấy ví dụ một cái máy tính. Máy tính được lắp ráp bởi các linh kiện rời cho nên một ngày nào đó nếu nó hư CPU thì bạn thay CPU mới, rất nhanh chóng và rẻ tiền. Chuyện gì xẩy ra nếu máy tính là một cục gắn liền CPU, RAM và ổ cứng. Vậy thì có phải càng tách rời các thành phần trong 1 ứng dụng, ứng dụng càng dễ phát triển, bảo trì.


Bởi vì Spring chỉ đóng vai trò là tầng business cho nên không thể dùng mỗi Spring để xây dựng ứng dụng được mà cần thêm 2 tầng nữa (thực chất Spring cũng cung cấp các dịch vụ ở tầng GUI là Webspring nhưng hẳn nhiên là Microsoft nổi tiếng về phần mềm chứ phần cứng thì còn phải học hỏi nhiều). Spring cũng biết khả năng của mình cho nên trong số 1000 lớp/interface Spring dành khá nhiều để hỗ trợ cho các framework khác tích hợp với nó.

Lựa chọn framework cho 2 tầng còn lại (Hiện Spring đang hỗ trợ)
Tùy theo thói quen và sở trường của mỗi người, sau đây là một số gợi ý:
+ Tầng persistence: JDBC, Hibernate, JDO, iBATIS, OJB..
Trong số này Hibernate là framework ORM (Object Relation Mapping) nổi tiếng nhất.

+ Tầng GUI: web (spring MVC, Velocity, FreeMarker, Strut, Tapestry, JSF, Webwork..) (tham khảo [1]), desktop (Swing..)
Strut là web framework rất nổi tiếng ở Việt nam cũng như thế giới nhưng hiện nay project này đã bị đóng băng, giống như Honda không sản xuất Cub81 nữa.
JSF là web framework do Sun đề xướng, Sun là cha đẻ của Java mà, cho nên chắc cũng có nhiều tuyệt chiêu lắm.
Webwork là một web framework mới khá mạnh mẽ. Điểm đặc biệt là webwork còn có khả năng Inversion of Control như Spring nữa.

Nếu có dịp, tôi sẽ trở lại so sánh cụ thể hơn về mạnh yếu của cá c web framework trên.

FAQ
Làm thế nào để viết một ứng dụng tích hợp giữa mấy cái nổi tiếng lại với nhau (ví dụ Hibernate, Spring, Webwork)?
Tôi sẽ minh hoạ bằng cách ví dụ trong bài tới

Tham khảo
[1] Walls Craig, Ryan Breidenbach ,"Spring in Action", Manning 2005

Hãy bắt đầu bằng một ví dụ đơn giản theo kiểu workthrough
Yêu cầu: viết 1 ứng dụng cho quản lý sinh viên đơn giản cho phép thêm xoá sửa các sinh viên. Thông tin mỗi sinh viên bao gồm: mã số (id, khóa chính, kiếu số), họ tên (kiểu String), tuổi (kiểu số).


DEMO SPRING + HIBERNATE

Bước 1. Thiết kế database
Database này có 1 bảng tên là Student(id, name, age). Để đơn giản, ta sẽ không tạo database bằng mysql hay access mà dùng hsql là 1 dbms ảo chạy trong bộ nhớ.

Bước 2. Tạo project bằng 1 IDE cụ thể như Eclipse hoặc JBuilder. Để đơn giản thì tất cả các file class java, file cấu hình xml sẽ được để cùng 1 thư mục.

Bước 3. Tạo class Student

Bước 4. Tạo file cấu hình cho Hibernate (hibernate.cfg.xml)

Bước 5. Tạo file cấu hình để ánh xạ lớp Student vào database (Student.hbm.xml)

Bước 6. Tạo file cấu hình cho Spring (beans.xml)

Bước 7. Tạo lớp để quản lý sinh viên StudentManager.