Tags:

Tìm hiểu về Maven Dependency Scope

Maven là một trong những build tool được sử dụng phổ biến trong hệ sinh thái Java. Trong bài viết này chúng ta sẽ cùng nhau tìm hiểu 2 khái niệm quan trọng đó là dependency scope và các loại dependency được maven sử dụng để giúp chúng ta quản lý các dependency trong maven project.

Các loại dependency trong Maven

Trong Maven, có 2 loại dependency chính là: direct transitive.

Direct dependency là các dependency được sử dụng và khai báo trực tiếp trong pom.xml thông qua thẻ <dependency>.

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

Transitive dependency là những dependency được sử dụng bởi các direct dependency. Các transitive dependency được thêm vào project một cách tự động. 

Chúng ta có thể liệt kê tất cả các dependencu được sử dụng trong project bao gồm direct và transitive dependency bằng cách sử dụng lệnh:  mvn dependency:tree.

Dependency Scope

Maven có 6 dependency scope chính: compile, provided, runtime, test, system, import. Việc hiểu những dependency scope này rất quan trọng để chúng ta có thể sử dụng scope đúng đắn trong các trường hơp khác nhau.

Compile

Đây là scope mặc định khi chúng ta không chỉ định scope cho một dependency khai báo trong pom.xml. Các dependency với compile scope sẽ luôn tồn tại trên classpath của project trong mọi tác vụ build.

<dependency>
    <groupId>commons-lang</groupId>
    <artifactId>commons-lang</artifactId>
    <version>2.6</version>
</dependency>

Để hiểu rõ hơn, giả sử trong project có sử dụng commons-lang dependency được khai báo như sau:

<dependency>
    <groupId>commons-lang</groupId>
    <artifactId>commons-lang</artifactId>
    <version>2.6</version>
</dependency>

Thì khi chúng ta sử dụng các lệnh maven compile, package hoặc install thì commons-lang đều sẽ tồn tại trên classpath. Đều này là rất cần thiết, nếu như các bạn sử dụng provide scope thì lúc install commons-lang dependency sẽ không có trên classpath, khi chạy gói jar được build ra có thể các bạn sẽ gặp lỗi ClassNotFound.

Provided

Scope này được dùng để đánh dấu một dependency sẽ được cung cấp tại thời điểm runtime bởi JDK hoặc container.

Ví dụ chúng ta có thể sử dụng provided scope cho các ứng dụng web được deploy lên container mà tại container này đã chứa sẵn các dependency được khai báo với provided scope. Ví dụ cụ thể là một Web server đã cung cấp sẵn Servlet API tại runtime vì thế chúng ta có thể khai báo dependency này với provided scope.

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
</dependency>

Các provided dependency chỉ có sẵn trên classpath tại compile-time và test.

Runtime

Các runtime dependency được sử dụng tại runtime nhưng chúng không cần thiết trong quá trình biên dịch mã của project. Do đó, các dependency được đánh dấu runtime scope sẽ hiện diện trong classpath tại runtime và test, nhưng chúng sẽ bị thiếu trong compile classpath.

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>6.0.6</version>
    <scope>runtime</scope>
</dependency>

Để hiểu rõ hơn về scope runtime, chúng ta quay lại mysql-connector-java dependency. Lý do mà nó có thể sử dụng với runtime scope là nó hoàn toàn không được sử dụng trong mã code, tất là trong mã code của chúng ta không có chỗ nào sử dụng trực tiếp các API từ mysql-connector-java dependency mà chỉ thông qua các interface ở trên. Đến khi chương trình chạy thì mysql-connector-java (JDBC driver) mới được tải động lên và sử dụng trong quá trình ứng dụng chạy. 

Test

Test scope được sử dụng để chỉ những dependency không cần thiết khi ứng dụng chạy, nó chỉ hữu ích cho mục đích kiểm thử ứng dụng. Các Test scope dependency sẽ không có tính chất transitive và chúng chỉ tồn tại trên classpath khi chúng ta thực thi test.

Một ví dụ rất điển hình cho scope này đó là junit.

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

System

System scope tương đối giống với provided scope. Điểm khác nhau lớn nhất giữa chúng đó là system scope yêu cầu chúng ta chỉ rõ đường dẫn đến file jar trong máy. 

Một điểm rất lo ngại khi sử dụng System scope đó là dự án có thể không chạy được trên các máy khác nhau do vị trí đặt file jar có thể khác trên các máy khác nhau.

<dependency>
    <groupId>com.baeldung</groupId>
    <artifactId>custom-dependency</artifactId>
    <version>1.3.2</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/libs/custom-dependency-1.3.2.jar</systemPath>
</dependency>

Import

Import scope được thêm vào ở phiên bản Maven 2.0.9 và nó chỉ sử dụng được với các dependency có type pom.

<dependency>
    <groupId>com.deft</groupId>
    <artifactId>mylib</artifactId>
    <version>1.0.0</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

Tóm lược

Qua bài viết chúng ta đã tìm hiểu được 2 cơ chế quan trọng đó là maven scope và các loại dependency trong maven được maven sử dụng để quản lý các dependency trong project. Hy vọng các bạn có thể hiểu rõ và sử dụng maven scope đúng đắn nhất trong các dự án tiếp theo.

Nguồn tham khảo

https://www.baeldung.com/maven-dependency-scopes

https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

https://stackoverflow.com/questions/12272499/maven-what-is-the-runtime-scope-purpose

5 1 vote
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x