Bộ sưu tập

Giới thiệu về Spring framework


https://codersontrang.com/2013/01/20/gioi-thieu-ve-spring-framework/

Spring là một trong những framework của Java được sử dụng phổ biến nhất tính đến thời điểm này. Không phải ngẫu nhiên mà bản thân Spring có được tiếng tăm ấy, bài viết này xin được phép giới thiệu một chút về Spring và những đặc tính vượt trội, ưu việt của nó trong việc tạo ra các ứng dụng đòi hỏi sự bộ phận hóa và có khả năng sử dụng lại cao. Như chúng ta đã biết, một ứng dụng thiết kế hướng đối tượng bao giờ cũng đặt việc tạo ra các thành phần riêng rẽ độc lập và có tính sử dụng lại cao lên làm ưu tiên hàng đầu. Bởi vì một khi đã tạo ra các thành phần như vậy, chúng ta sẽ tiết kiệm được rất nhiều thời gian và công sức trong quá trình tạo và bảo trì hệ thống sau này. Tuy nhiên, điều này quả là không dễ dàng bởi vì tính độc lập của các thành phần sẽ bị giảm đi do cách các thành phần liên kết với nhau. Với Spring, có được tiếng tăm như ngày hôm nay, chính là do framework này có cách tạo và liên kết các thành phần rất riêng và hữu ích.

Spring được ra đời bắt đầu từ ý tưởng trong một đoạn code của Rod Johnson trong thời điểm mà J2EE 1.3, 1.4 đang thịnh hành. Trong thời gian đó, mặc dù J2EE được sử dụng rộng rãi nhưng việc tạo ra một ứng dụng sử dụng framework này không hề đơn giản và dễ dàng vì các đoạn mã viết trên EJB khá phức tạp và khó để quản lý. Và Rod, đã miêu tả về một kiến trúc có thể giảm thiểu độ phức tạp trong quá trình lập trình phía server và kết quả đã gây sự chú ý của công đồng Java thế giới lúc đó. Về sau, Rod và tổ chức của ông đã tiếp tục ý tưởng để tạo ra một framework, cái mà chúng ta gọi là Spring là một sự thay thế mã nguồn mở cho các công nghệ liên quan đến J2EE đã lỗi thời.

Spring nổi bật ở cách nó liên kết các thành phần trong hệ thống lại với nhau. Sự liên kết được thực hiện bởi hai đặc tính cơ bản và quan trọng nhất của Spring là Dependency Injection và Inversion of Control (IoC). Để hiểu được hai khái niệm trừu tượng này, hãy xem một ví dụ cụ thể về cách Spring liên kết các thành phần lại với nhau như thế nào trước khi chúng ta đi đến định nghĩa của hai khái niệm.

Ví dụ của chúng ta là một ví dụ rất đơn giản. Với IDE là Eclipse, tạo một Java project với cấu trúc như hình dưới đây

hautudu_spring_demo_1

Trong cấu trúc trên, ta có một interface là Animal với phương thức trừu tượng là makeSound(). Các lớp Dog, Cat cài đặt interface Animal này. Một lớp House có chứa hai tham chiếu thuộc kiểu Animal. Và cuối cùng là lớp FarmTest có chứa phương thức main(). Cụ thể sẽ như ở dưới đây

Animal.java


package com.wordpress.hautudu.farm;

public interface Animal {
     public String makeSound();
}

Dog.java – Cài đặt interface Animal


package com.wordpress.hautudu.farm;

public class Dog implements Animal{

     @Override
     public String makeSound() {
           return "Dog makes sound";
     }

}

Cat.java – Cài đặt interface Animal


package com.wordpress.hautudu.farm;

public class Cat implements Animal{

	@Override
	public String makeSound() {
		return "Cat makes sound";
	}
}

House.java – chứa hai tham chiếu có kiểu Animal


package com.wordpress.hautudu.farm;


public class House {
	private Animal animal1;
	private Animal animal2;

	
	public Animal getAnimal1() {
		return animal1;
	}


	public void setAnimal1(Animal animal1) {
		this.animal1 = animal1;
	}


	public Animal getAnimal2() {
		return animal2;
	}


	public void setAnimal2(Animal animal2) {
		this.animal2 = animal2;
	}
}

FarmTest.java – chứa phương thức main(), trước tiên chúng ta hãy bắt đầu với một chương trình đơn giản như sau.


package com.wordpress.hautudu.farm;

public class FarmTest {
	public static void main(String [] args){
		House house = new House();
		Animal animal1 = new Dog();
		Animal animal2 = new Cat();
		house.setAnimal1(animal1);
		house.setAnimal2(animal2);
		
		System.out.println("Animal 1: "+house.getAnimal1().makeSound());
		System.out.println("Animal 2: "+house.getAnimal2().makeSound());
	}
}

Khi chạy chương trình trên, kết quả sẽ như sau

hautudu_spring_demo_2

Ở chương trình trên, hai đối tượng của hai lớp Dog và Cat lần lượt được khởi tạo và được gán vào hai tham chiếu trong một đối tượng của lớp House. Với việc liên kết các thành phần như trên, sẽ có hạn chế đó là việc liên kết các thành phần diễn ra ở trong Java code, điều này có nghĩa là khi chúng ta muốn thay đổi một thành phần nào đó trong liên kết, toàn bộ code phải biên dịch lại. Như vậy sẽ không dễ dàng trong việc bảo trì hệ thống. Hạn chế trên sẽ được khắc phục bởi Spring, mọi việc khởi tạo các thành phần và liên kết chúng lại với nhau sẽ được thực hiện ở trên một file cấu hình (.xml) thay vì trên Java code. Chính vì thế, về sau khi chúng ta muốn thay đổi, chúng ta chỉ cần sửa trên file cấu hình này và sẽ không phải biên dịch lại code nữa. Dưới đây sẽ là minh họa cụ thể cho việc áp dụng Spring vào ví dụ của chúng ta.

Để sử dụng Spring, chúng ta thêm hai thư viện vào project là spring.jarcommon-logging.jar, các thư viện này sẽ được đặt trong thư mục lib (thư viện của spring framework có thể download tại đây). Ngoài ra như đã nói chúng ta sẽ có thêm file cấu hình có tên là beans.xml. Và cấu trúc project bây giờ sẽ như sau:

hautudu_spring_demo_3

Chú ý là ta phải có bước cấu hình các thư viện như sau: Click chuột phải vào project chọn Properties, sau đó chọn Java Build Path, chọn tab Libraries rồi chọn Add JARs, tìm đến hai thư viện trong cây thư mục và nhấp OK để add hai thư viện này vào như hình dưới đây

hautudu_spring_demo_4

Và dưới đây là nội dung của file cấu hình beans.xml


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

	<bean id="dogBean" class="com.wordpress.hautudu.farm.Dog"/>

	<bean id="catBean" class="com.wordpress.hautudu.farm.Cat"/>

	<bean id="houseBean" class="com.wordpress.hautudu.farm.House">
		<property name="animal1" ref="dogBean"/>
		<property name="animal2" ref="catBean"/>
	</bean>

</beans>

Ta có thể để ý cách mà các thành phần được khởi tạo và liên kết với nhau trong file cấu hình trên. Tag <bean> được sử dụng để biểu diễn một đối tượng của một lớp nào đó. Mỗi đối tượng sẽ có một id và kiểu được thể hiện lần lượt qua các thuộc tính idclass bên trong tag <bean>. Ví dụ như trong file trên, ta có ba tag <bean> để khởi tạo 3 đối tượng của ba lớp tương ứng là Dog, Cat, và House. Đó là cách để khởi tạo một thành phần, ngoài ra đối tượng của lớp House có hai tham chiếu đến hai đối tượng của hai lớp Dog và Cat bằng việc sử dụng thuộc tính ref trong thẻ <property>, đó là cách các thành phần được liên kết với nhau trong Spring.

Trở lại với chương trình, bằng việc sử dụng Spring, giờ đây khởi tạo các thành phần và liên kết chúng lại với nhau sẽ không còn phải thực hiện trong Java code nữa. Chính vì thế lớp FarmTest.java của chúng ta sẽ được thay đổi như sau:

FarmTest.java


package com.wordpress.hautudu.farm;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class FarmTest {
	public static void main(String [] args){
		ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
		BeanFactory factory = (BeanFactory) context;
		House house = (House) factory.getBean("houseBean");
		
		System.out.println("Animal 1: "+house.getAnimal1().makeSound());
		System.out.println("Animal 2: "+house.getAnimal2().makeSound());
	}
}

Khi chương trình bắt đầu chạy, một đối tượng của ApplicationContext sẽ được khởi tạo và được cung cấp về vị trí của file cấu hình. Trong trường hợp cụ thể này, đối tượng context trên sẽ là một đối tượng của lớp ClassPathXmlApplicationContext và file cấu hình chính là beans.xml. Dưới đây là danh sách một số các ApplicationContext hay được sử dụng nhất.

  • ClassPathXmlApplicationContext: Được dùng để load các thông tin từ file cấu hình nằm trong classpath của ứng dụng. Chính vì thế mà chúng ta thấy tại sao file beans.xml trong ví dụ trên được đặt nằm bên trong thư mục src của project
  • FileSystemXmlApplicationContext: Được dùng để load các thông tin từ file cấu hình nằm trong hệ thống file trên máy của chúng ta. Ví dụ nếu file cấu hình beans.xml nằm trong ổ C: thay vì nằm trong project, ta có thể load thông tin từ file này như sau
    ApplicationContext context = new FileSystemXmlApplicationContext("C:/beans.xml");
  • XmlWebApplicationContext: Được dùng để load các thông tin từ file cấu hình nằm trong ứng dụng web. Mặc định, thông tin sẽ được load từ file cấu hình /WEB-INF/applicationContext.xml

Với các thông tin mà file cấu hình cung cấp, Spring container sẽ khởi tạo các thành phần cần thiết và liên kết chúng lại với nhau (quá trình liên kết còn gọi là bean wiring, hay bean injection). Còn một điểm nữa là đối tượng context cũng là một loại của BeanFactory cho nên ta hoàn toàn có thể ép kiểu nó và dùng nó để lấy ra các thành phần (hay còn gọi là các bean) được khởi tạo, liên kết và quản lý bởi Spring container chẳng hạn như trường hợp của houseBean trong ví dụ trên. Và tất nhiên là đối tượng house lấy ra sẽ chứa sẵn hai tham chiếu đến hai đối tượng của hai lớp Dog và Cat giống như ta đã định nghĩa trong file cấu hình thay vì phải lần lượt khởi tạo và gán chúng trong Java code. Kết quả khi chạy chương trình vẫn giống như trước được thể hiện ở hình dưới đây:

hautudu_spring_demo_5

Như vậy, qua ví dụ, chúng ta phần nào nắm được tư tưởng của Spring và khả năng đặc biệt của nó trong việc khởi tạo và liên kết các thành phần trong hệ thống. Tư tưởng chỉ có vậy, nhưng khi được biểu đạt ra ngoài, chúng ta cần phải biết đến hai khái niệm cơ bản sau:

  • Dependency Injection (bean injection, bean wiring): Là khả năng liên kết giữa các thành phần lại với nhau trong Spring, đó chính là việc các thuộc tính trong một đối tượng được “tiêm chích” để tham chiếu lần lượt đến các đối tượng khác được quản lý bởi Spring container. Đó chính là trường hợp houseBean trong ví dụ của chúng ta khi mà hai thuộc tính của nó là animal1 và animal2 được tiêm chích để tham chiếu đến hai đối tượng lần lượt của hai lớp Dog và Cat
  • Inversion of Control (IoC): Đó chính là khả năng của Spring container trong việc quản lý các thành phần, khi mà thay vì một thành phần phải tự đòi hỏi các tài nguyên cho nó, thì nó sẽ được Spring container cung cấp các tài nguyên dựa vào thông tin trong file cấu hình. Trong ví dụ trên, thay vì đối tượng của lớp House (thành phần) phải tự gán các tham chiếu animal1 và animal2 (tài nguyên) đến các đối tượng của lớp Dog và Cat thì việc này được đẩy ngược hoàn toàn cho phía container trong quá trình bắt đầu chạy chương trình.

Hai khái niệm trên có lẽ hơi trừu tượng, và na ná giống nhau. Tuy nhiên, chúng ta hãy cứ nhớ Dependency Injection là mô tả về khả năng liên kết các thành phần trong Spring, còn Inversion of Control mô tả cho khả năng đảo ngược luồng trong việc cung cấp các tài nguyên đến các thành phần của Spring container.

Cuối cùng, bài viết hi vọng bạn đọc có được những kiến thức cơ bản nhất về Spring framework, một trong những framework cho phép xây dựng các ứng dụng mà ở đó tính sử dụng lại của các thành phần, khả năng linh động trong việc sửa đổi được nâng cao và cải thiện. Chúng ta sẽ còn có nhiều các bài viết tiếp sau liên quan đến các kiến thức về Spring framework.

Advertisements
By Coder Sơn Trang Posted in Spring

31 comments on “Giới thiệu về Spring framework

  1. Inversion of Control (IoC) là một khái niệm chung chung, nó có thể biểu diễn dưới nhiều dạng khác nhau. Dependency Injection (DI) là một sự biểu diễn cụ thể của IoC, cho nên trong Spring, DI chính là IoC. và chúng là luôn nhơ rằng, điểm tạo nên sự khác biệt của Spring đó chính là DI, đây giống như Linh hồ của Spring Framework.

    Số lượt thích

Trả lời

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Đăng xuất /  Thay đổi )

Google photo

Bạn đang bình luận bằng tài khoản Google Đăng xuất /  Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Đăng xuất /  Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Đăng xuất /  Thay đổi )

Connecting to %s