Bài viết này mình xin hướng dẫn cho các bạn biết cách cơ bản nhất để khởi tạo các đối tượng trong Spring container, đó chính là sử dụng tập tin XML các bạn nhé!
Mình xin lấy lại cái ví dụ mà mình đã đưa ra trong bài viết Hiểu về Dependency Injection.
Ở đây, mình có một interface tên là Shape:
1 2 3 4 5 |
package com.huongdanjava.springxmlconfiguration; public interface Shape { public void draw(); } |
Một đối tượng hiện thực interface Shape là Circle:
1 2 3 4 5 6 7 |
package com.huongdanjava.springxmlconfiguration; public class Circle implements Shape { public void draw() { System.out.println("Drawing circle ..."); } } |
Đối tượng Drawing dùng để vẽ:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
package com.huongdanjava.springxmlconfiguration; public class Drawing { private Shape shape; public Drawing(Shape shape) { this.shape = shape; } public void setShape(Shape shape) { this.shape = shape; } public void preparing() { System.out.println("Preparing ..."); } public void draw() { shape.draw(); } } |
Một tập tin cấu hình của Spring nằm trong thư mục src/main/resources với nội dung ban đầu như sau:
1 2 3 4 5 |
<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"> </beans> |
Và bên dưới là Maven project của mình:
Để làm việc với Spring framework thì chúng ta cần phải thêm dependency của nó vào tập tin pom.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.huongdanjava</groupId> <artifactId>spring-xml-configuration</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>6.0.2</version> </dependency> </dependencies> </project> |
OK, bây giờ chúng ta sẽ khởi tạo đối tượng Circle trước các bạn nhé! Vì đối tượng này không phụ thuộc vào đối tượng khác nên chúng ta chỉ cần khởi tạo nó với một id trong Spring container:
1 2 |
<bean id="shape" class="com.huongdanjava.springxmlconfiguration.Circle"> </bean> |
Đến đối tượng Drawing, ở đây đối tượng Drawing có phụ thuộc vào đối tượng Circle mà chúng ta đã tạo ra trong Spring container, do đó chúng ta cần có cách để đưa đối tượng Circle vào đối tượng Drawing.
Như các bạn thấy trong code của Drawing, chúng ta có thể đưa đối tượng Circle vào đối tượng Drawing bằng hai cách: bằng constructor hoặc bằng phương thức setShape(). Vậy trong Spring mình sẽ làm điều này như thế nào?
Đầu tiên, các bạn sẽ khai báo đối tượng Drawing mà chưa đưa các phụ thuộc của nó vào, các bạn có thể khai báo nó giống như khởi tạo đối tượng Circle:
1 2 |
<bean id="drawing" class="com.huongdanjava.springxmlconfiguration.Drawing"> </bean> |
Rồi bây giờ mình sẽ đưa đối tượng Circle vào đối tượng Drawing bằng constructor, cái này tiếng Anh có thể gọi là Constructor Injection.
1 2 3 |
<bean id="drawing" class="com.huongdanjava.springxmlconfiguration.Drawing"> <constructor-arg ref="shape" /> </bean> |
Hoặc là bằng phương thức setShape(), tiếng Anh có thể gọi là Setter Injection.
Đối với cách này, đối tượng Drawing của bạn phải khai báo thêm một constructor mặc định bởi vì Spring sẽ dùng constructor này để khởi tạo đối tượng Drawing, nghĩa là lớp Drawing phải viết lại như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.huongdanjava.springxmlconfiguration; public class Drawing { private Shape shape; public Drawing() {} public Drawing(Shape shape) { this.shape = shape; } public void setShape(Shape shape) { this.shape = shape; } public void preparing() { System.out.println("Preparing ..."); } public void draw() { shape.draw(); } } |
Giờ chúng ta có thể đưa đối tượng Circle vào như sau:
1 2 3 |
<bean id="drawing" class="com.huongdanjava.springxmlconfiguration.Drawing"> <property name="shape" ref="shape" /> </bean> |
Các bạn có thể sử dụng một trong hai cách trên tùy theo code của bạn.
Giờ chúng ta hãy chạy thử xem, ở đây mình sẽ chọn Setter Injection cho đối tượng Drawing, chi tiết tập tin cấu hình của Spring như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<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="drawing" class="com.huongdanjava.springxmlconfiguration.Drawing"> <constructor-arg ref="shape" /> </bean> --> <bean id="drawing" class="com.huongdanjava.springxmlconfiguration.Drawing"> <property name="shape" ref="shape" /> </bean> <bean id="shape" class="com.huongdanjava.springxmlconfiguration.Circle"> </bean> </beans> |
Và ví dụ để chạy:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.huongdanjava.springxmlconfiguration; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Application { public static void main(String[] args) { // Call Spring container ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); // Request to get Drawing object Drawing drawing = (Drawing) context.getBean("drawing"); drawing.draw(); } } |
Kết quả:
tuyet
Hàm setShape(Shape shape) trong lớp Drawing có phải là thừa không anh.
Vì em thấy trong xml anh khai báo “” nên sẽ tự hiểu đối tượng shape của lớp Drawing.
Khanh Nguyen
Chỗ nào khai báo “” đâu ta?
Trường
Vâng em hiểu rồi, anh phải nói rõ là cái setter đó phải đặt tên theo setter bên class, không trùng tên là lỗi ngay
Khanh Nguyen
Anh có nói rõ trong bài viết này https://huongdanjava.com/vi/noi-them-ve-setter-injection-trong-spring-su-dung-tap-tin-xml.html.
Em tham khảo thêm nhé.
Trường
Bây giờ có thêm 1 lớp nữa impl Shape, rồi gán setter vào Drawing. Vậy là trong bean có 2 setter, lúc gọi thì nó dùng cái nào?
Khanh Nguyen
Trong bean có 2 setters là sao em? Thật ra chỉ có 1 thôi.
Long
Giờ em mún làm ví dụ này trong Spring Boot thì làm thế nào hả anh :D. Em không biết phải code dòng này “ApplicationContext context = new ClassPathXmlApplicationContext(“spring.xml”);
” như thế nào trong SpringBoot.
Cám ơn anh đã đọc tin.
Khanh Nguyen
Spring Boot hỗ trợ chúng ta khởi tạo bean sử dụng các annotation, em không cần phải khai báo trong tập tin XML. Do đó, em không cần phải khai báo dòng code trên nữa.
Anh sẽ cố gắng viết một bài cơ bản về Spring Boot. Em chờ đón đọc nhé!
Cảm ơn em đã ủng hộ Hướng Dẫn Java!
Trung
anh ơi, ví dụ trên là output ra chữ Drawing circle, em giả sử có thêm 1 class tam giác cũng implement Shap thì output là gì hả anh. vì ở ví dụ trên chỉ có mỗi circle cài đặt Shape
Khanh Nguyen
Nếu em có thêm đối tượng Triangle implement interface Shape thì em có thể khai báo đối tượng này trong khung chứa của Spring, rồi sau đó dùng attribute ref để gán nó vào đối tượng Drawing bằng constructor hoặc setter cũng được.
Khi đó, output nó sẽ là cho đối tượng Triangle em nhé.
hải
anh ơi bài viết spring cua anh hay qua, anh làm hoàn chỉnh luôn đi anh