Trong bài viết về Bean autowiring trong Spring, mình đã giới thiệu với các bạn 3 cách để có thể tự động đưa đối tượng phụ thuộc vào đối tượng bị phụ thuộc mà không cần phải sử dụng các thuộc tính ref hay list.
Trong bài viết này, mình sẽ giới thiệu với các bạn một cách khác để làm điều này, đó chính là sử dụng @Autowired annotation. Hãy xem làm thế nào để sử dụng annotation này các bạn nhé!
Mình vẫn sử dụng lại ví dụ trong bài viết Bean autowiring trong Spring là gì để làm ví dụ.
Mình sẽ xóa autowire=“constructor” trong khai báo bean room, bây giờ bạn chạy lại ứng dụng:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.huongdanjava.springbeanautowiring; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Application { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); Room room = (Room) context.getBean("room"); if (room.getTable() != null) { System.out.println(room.getTable().toString()); } } } |
sẽ thấy bean table không còn được đưa vào bean room nữa.
OK, giờ chúng ta sẽ sử dụng @Autowired annotation để đưa lại bean table vào trong bean room nhé các bạn.
Đầu tiên, chúng ta cần phải khai báo @Autowired annotation trong class Room cho biến của đối tượng Table. Các bạn có thể khai báo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package com.huongdanjava.springbeanautowiring; import org.springframework.beans.factory.annotation.Autowired; public class Room { @Autowired private Table table; public Room() {} public Room(Table table) { this.table = table; } public Table getTable() { return table; } public void setTable(Table table) { this.table = table; } } |
hoặc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package com.huongdanjava.springbeanautowiring; import org.springframework.beans.factory.annotation.Autowired; public class Room { private Table table; public Room() {} @Autowired public Room(Table table) { this.table = table; } public Table getTable() { return table; } public void setTable(Table table) { this.table = table; } } |
hoặc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package com.huongdanjava.springbeanautowiring; import org.springframework.beans.factory.annotation.Autowired; public class Room { private Table table; public Room() {} public Room(Table table) { this.table = table; } public Table getTable() { return table; } @Autowired public void setTable(Table table) { this.table = table; } } |
Để sử dụng @Autowired annotation, chúng ta cần đăng ký đối tượng AutowiredAnnotationBeanPostProcessor với Spring. Có hai cách để chúng ta có thể làm điều đó:
– Sử dụng <context:annotation-config />
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config /> <bean id="table" class="com.huongdanjava.springbeanautowiring.Table"> <property name="code" value="123456" /> </bean> <bean id="room" class="com.huongdanjava.springbeanautowiring.Room"> </bean> </beans> |
<context:annotation-config /> tag được khai báo để sử dụng các đối tượng phù hợp liên quan đến các annotation đã được khai báo trong các bean đã khởi tạo trong Spring container.
Trong bài viết này, mình sử dụng <context:annotation-config /> tag để tự động khởi tạo đối tượng AutowiredAnnotationBeanPostProcessor vì chúng ta đang sử dụng @Autowired annotation.
– Sử dụng trực tiếp AutowiredAnnotationBeanPostProcessor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<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 class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" /> <bean id="table" class="com.huongdanjava.springbeanautowiring.Table"> <property name="code" value="123456" /> </bean> <bean id="room" class="com.huongdanjava.springbeanautowiring.Room"> </bean> </beans> |
Kết quả:
truong
Anh ơi cho em hỏi em dùng @Autowired để đưa trực tiếp giá trị phụ thuộc vào giá trị bị phụ thuộc khi chạy project rồi, nhưng trong thời gian chạy em muốn load lại giá trị phụ thuộc mà không phải chạy lại project thì phải làm thế nào ạ?
Khanh Nguyen
Load lại là sao ta? Không hiểu ý em lắm!
truong
Ví dụ là em tạo 1 bean là lớp sinh viên, sau đó em định nghĩa danh sách sinh viên trong lớp sinh viên nay trong file xml rồi dùng @autowired để gán giá tri cho lớp sinh viên trên, việc này diễn ra tự động khi em khới động server để chạy project này. Sau khi project đã được chạy vào 1 thời điểm nào đó em cập nhật lại file xml để thêm 1 sinh viên nào đó nhưng vì bean danh sách sinh viên đã được khởi tạo từ đầu nên nó sẽ không cập nhật lại danh sách của em trừ khi em khởi động lại server. Vậy nên em muốn click 1 nút nào đó có thể khởi tạo lại bean danh sách sinh viên này thay thế bean cũ đã được khởi tạo lúc đầu.
Khanh Nguyen
Dùng database đi em, không ai làm như em cả 🙂
truong
Trong công ty em hiện đang phát triển trang web nội bộ bằng spring, em thấy có đối tượng là SqlSessionTemplate sẽ lấy các câu query đã được viết trên các file xml, đối tượng này sẽ được nạp giá trị tự động lúc khởi động server bằng @autowired. Nên là nếu sau này em muốn phát triển, thêm hoặc sửa các câu sql trong các file xml trên thì đều phải khởi động lại server, việc này sẽ không được khuyến khích nên em cần reload lại giá trị của bean chứa template sql trên ạ
Khanh Nguyen
Em đang sử dụng MyBatis?
truong
Đúng rồi anh!
Em đang dùng điện thoại nên không bấm reply được ở dưới =))
Khanh Nguyen
Không thay đổi cách mình lưu thông tin sinh viên được hả em? Sao bắt buộc phải dùng XML?
truong
Người ta muốn tách biệt phần sql và phần code ra đó anh, không muốn để sql trong java nữa và dùng mybatis để chống tấn công bằng sql nên dùng như vậy. Hệ thống nó rất lớn nên sql của mỗi hệ thống con cũng rất nhiều ạ
Khanh Nguyen
Anh ko rõ nhu cầu như thế nào? Thế nhưng nếu muốn cập nhập như vậy thì em cần phải reload lại bean chứa thông tin sinh viên trong Spring container. Hiện tại thì anh chưa có bài viết về cái này, em có thể research thêm trên Google nhé!
truong
Ok em cảm ơn
Long
e có một project nhỏ sử dụng autowiring annotation nhưng trong bean này không tự động đưa vào bean khác được thì do lỗi gì ạ. e có thể gửi project cho a xem được không
Khanh Nguyen
Gửi anh project của em đi! Google Drive cũng được 🙂
giang
anh ơi cho em hỏi giả sử như mình khởi tạo 2 đối tượng table , vậy thì khi khởi tạo đối tượng room thông qua bean nó sẽ lấy đối tượng nào , và cách giải quyết ra sao … kiến thức e còn hạn chế mong a bỏ qua
Khanh Nguyen
Sử dụng annotation @Qualifier đi em http://huongdanjava.com/su-dung-annotation-qualifier-trong-spring.html
Hải
Chào Bạn.
Sao có những ví dụ mình làm theo bạn copy import org.springframework.context.ApplicationContext; thì ok có nhưgx ví dụ copy đoạn này vào thì bị báo lỗi mong bạn giúp
Khanh Nguyen
Bạn có thể gửi error message để Khanh xem thế nào không?
Hải
Cám ơn Bạn đã phản hồi. Mình mắc một lỗi chung là đôi khi làm theo một ví dụ nào đó trên web. Khi copy câu lệnh import vào một class nào đó thì câu lệnh import nó báo lỗi. Bản thân câu lệnh import đó không có lỗi nhưng mình hiểu là package đó chưa đưa vào nằm đâu đó trogn project nên nó báo lỗi. Bạn làm ơn chỉ mình cách đưa gói đó vào dự án để câu lệnh import đó hết báo lỗi. Ví dụ mình có đoạn class
package com.example.demo;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
Nó báo lỗi tất cả các khai báo import mong bạn chỉ giúp
Hải
ok rồi thanks Bạn vì mình mới làm quen java nên còn lọgn ngọng mất cái này. Những bài vết của bạn về Spring rất bổ ích.
Khanh Nguyen
Rất vui khi bạn đã giải quyết được vấn đề.
Có gì cứ hỏi nhé!
Hoàng Hưng
Anh ơi thế cho e hỏi là khi dùng cái autowiring thì mặc định là kiểu byname ạ .Còn kiểu khác như bytype hay by construct thì như nào ạ
Khanh Nguyễn
Khi em đã sử dụng @Autowire annotation thì nó liên quan đến byType em nhé! Vì khi đó, Spring sẽ tự động tìm trong khung chứa của nó bean có cùng type với đối tượng mà em muốn autowire, để đưa vào đối tượng bị phụ thuộc.
byName và byConstructor thì không liên quan lắm.
BaoNam
vậy là cái @autowiring mình có thể viết ở attribute, constructor hay setter đều như nhau đúng không anh
Khanh Nguyễn
Đúng rồi đó em!