0Pricing
Java Academy · บทเรียน

บริการด้วย 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. module-info.java
  2. requires และ exports
  3. บริการด้วย provides/uses
  4. การย้ายไปใช้มอดูล
← กลับไปที่ Java Academy