Trong bài viết trước, mình đã hướng dẫn các bạn cách auto component scan sử dụng cấu hình trong tập tin XML. Trong bài viết này, mình hướng dẫn các bạn cách làm điều này với code Java sử dụng annotation @ComponentScan các bạn nhé!
Đầu tiên, mình sẽ tạo mới một Maven project để làm ví dụ:
Mình sẽ sử dụng Java 17 cho ứng dụng ví dụ này:
1 2 3 4 |
<properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties> |
Spring dependency như sau:
1 2 3 4 5 |
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>6.0.2</version> </dependency> |
Bây giờ, mình sẽ thêm một class HelloWorld được khai báo với annotation @Component như sau:
1 2 3 4 5 6 7 8 9 10 11 |
package com.huongdanjava.spring; import org.springframework.stereotype.Component; @Component public class HelloWorld { public void print() { System.out.print("Hello World!"); } } |
Tiếp theo mình sẽ tạo mới một class để cấu hình cho ứng dụng:
1 2 3 4 5 6 7 8 |
package com.huongdanjava.spring; import org.springframework.context.annotation.ComponentScan; @ComponentScan public class ApplicationConfiguration { } |
Như các bạn thấy, mình đã annotate class ApplicationConfiguration này với annotation @ComponentScan, mục đích của annotation @ComponentScan là tự động scan và khởi tạo bean trong Spring container cho các class được annotate với các annotation @Component, @Repository, @Service và @Controller.
Các attribute của annotation @ComponentScan như sau:
Annotation @ComponentScan cho phép chúng ta declare các package mà Spring có thể scan và khởi tạo bean. Mặc định, nếu chúng ta không declare attribute basePackages thì Spring sẽ lấy package chứa class mà chúng ta khai báo annotation @ComponentScan này, để scan. Bạn có thể khai báo attribute basePackages nếu muốn, ví dụ như sau:
1 2 3 4 5 6 7 8 |
package com.huongdanjava.spring; import org.springframework.context.annotation.ComponentScan; @ComponentScan("com.huongdanjava.spring") public class ApplicationConfiguration { } |
Annotation @ComponentScan còn cho phép chúng ta khai báo packages của những class mà chúng thuộc về để scan, sử dụng attribute basePackageClasses.
Chúng ta còn có thể định nghĩa cách tên các bean được generate (attribute nameGenerator), filter cho phép Spring được tạo bean cho class nào (attribute includeFilters), không cho phép tạo bean cho class nào (attribute excludeFilters) và tạo bean liền hay chỉ khi class đó được sử dụng mới tạo bean (attribute lazyInit), … Tuỳ nhu cầu thì các bạn hãy cấu hình annotation này cho đúng nhé!
Trong ví dụ của mình, class ApplicationConfiguration nằm cùng package với class HelloWorld nên mình không cần khai báo gì nữa cả.
Class main để chạy ứng dụng này có nội dung như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.huongdanjava.spring; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Application { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfiguration.class); HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld"); helloWorld.print(); } } |
Kết quả khi chạy ứng dụng vẫn giống như trong bài viết trước:
manh_uet
Em thắc mắc về tại sao annotation @ComponentScan tại sao anh lại đặt cùng với @Configuration mà không phải đặt với @Controller, @Service, @Component vậy anh? Hay là @Configuration sẽ được load trước tiên ngay khi chương trình chạy, trước cả (@Controller, @Service, @Component)
Khanh Nguyen
Class chứa annotation @Configuration sẽ giúp chúng ta cấu hình Spring bean cho ứng dụng, annotation @ComponentScan sẽ làm việc với annotation @Configuration này để scan tất cả các định nghĩa bean để khởi tạo bean trong Spring container đó bạn!
Khanh Nguyen
Mình đã sửa lại cho đúng. Trong trường hợp sử dụng annotation @ComponentScan, chúng ta không cần sử dụng annotation @Configuration nhé bạn!