บริการด้วย provides/uses
แยกส่วนด้วยตัวโหลดบริการ
บริการด้วย provides/uses เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
ลดการพึ่งพากันด้วยบริการ
โมดูลสามารถทำงานร่วมกันได้โดยไม่ต้องพึ่งพาการนำไปใช้งานของกันและกัน ด้วย รูปแบบตัวโหลดบริการ
โมดูลหนึ่งประกาศว่าใช้บริการด้วย uses ส่วนอีกโมดูลประกาศการนำไปใช้งานด้วย provides จากนั้น JVM จะเชื่อมโมดูลเหล่านี้เข้าด้วยกัน
บทบาททั้งสาม
บริการหนึ่งรายการมีผู้เกี่ยวข้องสามบทบาท:
- อินเทอร์เฟซบริการ: ข้อตกลงซึ่งอยู่ในโมดูลใดโมดูลหนึ่ง
- ผู้ให้บริการ: โมดูลที่จัดหาการนำไปใช้งาน
- ผู้ใช้บริการ: โมดูลที่โหลดการนำไปใช้งานขณะทำงาน
อินเทอร์เฟซบริการ
ขั้นแรกให้กำหนดข้อตกลง อินเทอร์เฟซนี้เป็นอินเทอร์เฟซทั่วไปในแพ็กเกจที่เปิดเผย เพื่อให้ทั้งผู้ให้บริการและผู้ใช้บริการสามารถอ้างอิงได้
package com.example.spi;
public interface Codec {
String name();
byte[] encode(String input);
}ผู้ใช้บริการประกาศการใช้
โมดูลผู้ใช้บริการประกาศว่าใช้บริการอินเทอร์เฟซนี้ด้วย uses ซึ่งเป็นการบอก JPMS ว่าโมดูลจะค้นหาการนำไปใช้งานผ่าน ServiceLoader
module com.example.app {
requires com.example.spi;
uses com.example.spi.Codec;
}ผู้ให้บริการประกาศการจัดหา
โมดูลผู้ให้บริการประกาศว่าอินเทอร์เฟซใดที่ตนนำไปใช้งานด้วย provides ... with ... พร้อมระบุชื่อคลาสจริงของตน
module com.example.base64 {
requires com.example.spi;
provides com.example.spi.Codec
with com.example.base64.Base64Codec;
}การนำไปใช้งานของผู้ให้บริการ
คลาสที่นำไปใช้งานเป็น Java ทั่วไป โดยต้องเป็นคลาสสาธารณะและมีตัวสร้างสาธารณะที่ไม่มีอาร์กิวเมนต์ หรือมีเมธอดสแตติกสาธารณะชื่อ provider()
package com.example.base64;
import com.example.spi.Codec;
import java.util.Base64;
public class Base64Codec implements Codec {
public String name() { return "base64"; }
public byte[] encode(String input) {
return Base64.getEncoder().encode(input.getBytes());
}
}การโหลดด้วย ServiceLoader
ขณะทำงาน ผู้ใช้บริการจะขอการนำไปใช้งานทั้งหมดที่มีจาก ServiceLoader.load(Codec.class) แล้ววนอ่านผลลัพธ์ โดยไม่มีการเชื่อมโยงขณะคอมไพล์กับการนำไปใช้งานใดโดยเฉพาะ
import com.example.spi.Codec;
import java.util.ServiceLoader;
public class App {
public static void main(String[] args) {
ServiceLoader<Codec> loader = ServiceLoader.load(Codec.class);
for (Codec codec : loader) {
System.out.println("Found codec: " + codec.name());
}
}
}เหตุใดจึงมีประสิทธิภาพ
ผู้ใช้บริการไม่เคยระบุชื่อคลาสของผู้ให้บริการ เพียงนำโมดูลผู้ให้บริการใหม่ไปไว้บนพาธโมดูล ระบบก็จะค้นพบโมดูลนั้นโดยอัตโนมัติ
วิธีนี้ทำให้สร้างสถาปัตยกรรมปลั๊กอินและการกลับทิศทางการพึ่งพาอย่างเป็นระเบียบได้
โรงงานสำหรับสร้างอินสแตนซ์
หากการสร้างอินสแตนซ์ต้องใช้ตรรกะ ให้เปิดเผยเมธอดสแตติกสาธารณะชื่อ provider() แทนตัวสร้างที่ไม่มีอาร์กิวเมนต์ JPMS จะเรียกเมธอดนี้เพื่อรับอินสแตนซ์
package com.example.base64;
import com.example.spi.Codec;
public class CodecFactory {
public static Codec provider() {
return new Base64Codec();
}
}ผู้ให้บริการหลายราย
หลายโมดูลสามารถจัดหาอินเทอร์เฟซเดียวกันได้แต่ละโมดูล ServiceLoader จะส่งกลับผู้ให้บริการทั้งหมด ทำให้ผู้ใช้บริการเลือกตามชื่อ ลำดับความสำคัญ หรือความสามารถได้
คุณสามารถเพิ่มหรือลบผู้ให้บริการได้โดยไม่ต้องแก้ไขโค้ดของผู้ใช้บริการ
สตรีมผ่านผู้ให้บริการ
ตั้งแต่ Java 9 เป็นต้นมา ServiceLoader มี stream() ซึ่งส่งมอบตัวจัดการ Provider ให้คุณกรองได้ก่อนสร้างอินสแตนซ์ เหมาะสำหรับกรณีที่การสร้างอินสแตนซ์ใช้เวลามาก
import com.example.spi.Codec;
import java.util.ServiceLoader;
public class App {
public static void main(String[] args) {
Codec chosen = ServiceLoader.load(Codec.class).stream()
.map(ServiceLoader.Provider::get)
.filter(c -> c.name().equals("base64"))
.findFirst()
.orElseThrow();
System.out.println("Using: " + chosen.name());
}
}ตรวจสอบอย่างรวดเร็ว
ลองทบทวนว่าแต่ละบทบาทใช้คำสั่งใด
สรุปทบทวน
คุณได้เรียนรู้รูปแบบบริการของโมดูลดังนี้:
- มีสามบทบาท ได้แก่ อินเทอร์เฟซบริการ ผู้ให้บริการ และผู้ใช้บริการ
- ผู้ใช้บริการใช้
usesส่วนผู้ให้บริการใช้provides ... with - โหลดการนำไปใช้งานขณะทำงานผ่าน
ServiceLoader - ผู้ให้บริการต้องมีตัวสร้างสาธารณะที่ไม่มีอาร์กิวเมนต์ หรือเมธอดสแตติก
provider()
ถัดไป: การย้ายโครงการเดิมไปใช้โมดูล
คำถามที่พบบ่อย
บทเรียน “บริการด้วย provides/uses” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “บริการด้วย provides/uses” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “บริการด้วย provides/uses”
แยกส่วนด้วยตัวโหลดบริการ คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “บริการด้วย provides/uses” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม
ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- module-info.java
- requires และ exports
- บริการด้วย provides/uses
- การย้ายไปใช้มอดูล