โปรแกรมสามารถขึ้นอยู่กับไลบรารีในระหว่างการคอมไพล์ แต่ไม่ใช่รันไทม์?


110

ผมเข้าใจความแตกต่างระหว่างรันไทม์และเวลารวบรวมและวิธีการแยกความแตกต่างระหว่างทั้งสอง แต่ผมก็ไม่เห็นความจำเป็นที่จะทำให้ความแตกต่างระหว่างเวลารวบรวมและรันไทม์อ้างอิง

สิ่งที่ฉันสำลักคือ: โปรแกรมจะไม่ขึ้นอยู่กับบางสิ่งบางอย่างในรันไทม์ที่ขึ้นอยู่ระหว่างการคอมไพล์ได้อย่างไร? หากแอป Java ของฉันใช้ log4j แสดงว่าต้องใช้ไฟล์ log4j.jar เพื่อที่จะคอมไพล์ (รหัสของฉันรวมเข้ากับและเรียกใช้เมธอดสมาชิกจากภายใน log4j) รวมถึงรันไทม์ (รหัสของฉันไม่สามารถควบคุมสิ่งที่เกิดขึ้นได้อย่างแน่นอนเมื่อโค้ดภายใน log4j .jar รัน)

ฉันกำลังอ่านข้อมูลเกี่ยวกับเครื่องมือแก้ปัญหาการพึ่งพาเช่น Ivy และ Maven และเครื่องมือเหล่านี้ทำให้ความแตกต่างระหว่างการอ้างอิงทั้งสองประเภทนี้อย่างชัดเจน ฉันไม่เข้าใจความจำเป็นของมัน

ใครช่วยให้คำอธิบายแบบ "King's English" แบบง่ายๆโดยเฉพาะตัวอย่างจริงที่แม้แต่คนยากจนอย่างฉันก็ยังเข้าใจได้


2
คุณสามารถใช้การสะท้อนและใช้คลาสที่ไม่สามารถใช้งานได้ในเวลาคอมไพล์ คิดว่า "ปลั๊กอิน"
Per Alexandersson

คำตอบ:


64

โดยทั่วไปจำเป็นต้องมีการพึ่งพาเวลาคอมไพล์ในรันไทม์ ใน maven การcompileอ้างอิงขอบเขตจะถูกเพิ่มลงใน classpath บนรันไทม์ (เช่นในสงครามพวกมันจะถูกคัดลอกไปยัง WEB-INF / lib)

อย่างไรก็ตามไม่ได้กำหนดไว้อย่างเคร่งครัด ตัวอย่างเช่นเราอาจรวบรวมกับ API บางตัวทำให้เป็นการพึ่งพาเวลาคอมไพล์ แต่ในรันไทม์รวมถึงการใช้งานที่รวม API ด้วย

อาจมีบางกรณีที่โครงการต้องการการพึ่งพาบางอย่างในการคอมไพล์ แต่ไม่จำเป็นต้องใช้โค้ดที่เกี่ยวข้อง แต่สิ่งเหล่านี้จะหายาก

ในทางกลับกันการรวมการอ้างอิงรันไทม์ที่ไม่จำเป็นในเวลาคอมไพล์เป็นเรื่องปกติมาก ตัวอย่างเช่นหากคุณกำลังเขียนแอปพลิเคชัน Java EE 6 คุณจะคอมไพล์กับ Java EE 6 API แต่ที่รันไทม์สามารถใช้คอนเทนเนอร์ Java EE ใด ๆ ก็ได้ เป็นคอนเทนเนอร์นี้ที่ให้การใช้งาน

การอ้างอิงเวลาคอมไพล์สามารถหลีกเลี่ยงได้โดยใช้การสะท้อน ตัวอย่างเช่นไดรเวอร์ JDBC สามารถโหลดด้วย a Class.forNameและคลาสที่โหลดจริงสามารถกำหนดค่าได้ผ่านไฟล์คอนฟิกูเรชัน


17
เกี่ยวกับ Java EE API นั่นไม่ใช่ขอบเขตการอ้างอิงที่ "ให้มา" หรือไม่?
Kevin

15
ตัวอย่างที่จำเป็นต้องมีการพึ่งพาเพื่อคอมไพล์ แต่ไม่จำเป็นในรันไทม์คือ lombok (www.projectlombok.org) jar ใช้เพื่อแปลงรหัส java ในเวลาคอมไพล์ แต่ไม่จำเป็นต้องใช้เลยในรันไทม์ การระบุขอบเขต "ให้" ทำให้โถไม่รวมอยู่ในสงคราม / โถ
Kevin

2
@Kevin ใช่จุดที่ดีprovidedขอบเขตจะเพิ่มการพึ่งพาเวลาคอมไพล์โดยไม่ต้องเพิ่มการพึ่งพารันไทม์ตามความคาดหวังว่าการอ้างอิงจะถูกจัดเตรียมไว้ที่รันไทม์ด้วยวิธีอื่น (เช่นไลบรารีที่ใช้ร่วมกันในคอนเทนเนอร์) runtimeในทางกลับกันจะเพิ่มการพึ่งพารันไทม์โดยไม่ทำให้เป็นการพึ่งพาเวลาคอมไพล์
Artefacto

ดังนั้นจึงปลอดภัยที่จะกล่าวว่าโดยปกติจะมีความสัมพันธ์แบบ 1: 1 ระหว่าง "การกำหนดค่าโมดูล" (โดยใช้คำว่า Ivy) และไดเร็กทอรีหลักภายใต้รูทโปรเจ็กต์ของคุณ ตัวอย่างเช่นการทดสอบ JUnit ทั้งหมดของฉันที่ขึ้นอยู่กับ JUnit JAR จะอยู่ภายใต้การทดสอบ / รูทเป็นต้นฉันไม่เห็นว่าคลาสเดียวกันที่บรรจุภายใต้รูทต้นทางเดียวกันสามารถ "กำหนดค่า" ให้ขึ้นอยู่กับที่แตกต่างกันได้อย่างไร JARs ในเวลาใดก็ได้ หากคุณต้องการ log4j คุณต้อง log4j; ไม่มีวิธีใดที่จะบอกให้รหัสเดียวกันเรียกใช้การโทร log4j ภายใต้การกำหนดค่า 1 รายการ แต่ให้ละเว้นการเรียก log4j ภายใต้การกำหนดค่า "ไม่บันทึก" บางอย่างใช่ไหม
IAmYourFaja

30

การพึ่งพา Maven แต่ละรายการมีขอบเขตที่กำหนดว่าคลาสพา ธ ใดที่การอ้างอิงพร้อมใช้งาน

เมื่อคุณสร้าง JAR สำหรับโปรเจ็กต์การอ้างอิงจะไม่รวมกับอาร์ติแฟกต์ที่สร้างขึ้น ใช้สำหรับการรวบรวมเท่านั้น (อย่างไรก็ตามคุณยังสามารถสร้าง maven รวมการอ้างอิงใน jar ที่สร้างขึ้นได้โปรดดู: รวมการอ้างอิงใน jar ด้วย Maven )

เมื่อคุณใช้ Maven เพื่อสร้างไฟล์ WAR หรือไฟล์ EAR คุณสามารถกำหนดค่า Maven ให้รวมกลุ่มการอ้างอิงกับอาร์ติแฟกต์ที่สร้างขึ้นและคุณยังสามารถกำหนดค่าให้แยกการอ้างอิงบางอย่างออกจากไฟล์ WAR โดยใช้ขอบเขตที่ให้มา

ขอบเขตที่พบบ่อยที่สุด - ขอบเขตการคอมไพล์ - บ่งชี้ว่าการอ้างอิงนั้นพร้อมใช้งานสำหรับโปรเจ็กต์ของคุณบนคลาสพา ธ การคอมไพล์การคอมไพล์การทดสอบยูนิตและคลาสพา ธ การดำเนินการและคลาสพา ธ รันไทม์ในที่สุดเมื่อคุณรันแอ็พพลิเคชันของคุณ ในเว็บแอ็พพลิเคชัน Java EE หมายความว่าการอ้างอิงจะถูกคัดลอกไปยังแอปพลิเคชันที่ปรับใช้ของคุณ อย่างไรก็ตามในไฟล์. jar การอ้างอิงจะไม่รวมอยู่ในขอบเขตการคอมไพล์ ..

ขอบเขตรันไทม์บ่งชี้ว่าการอ้างอิงนั้นพร้อมใช้งานสำหรับโปรเจ็กต์ของคุณบนการดำเนินการทดสอบหน่วยและคลาสพา ธ การดำเนินการรันไทม์ แต่ต่างจากขอบเขตการคอมไพล์ที่จะไม่พร้อมใช้งานเมื่อคุณรวบรวมแอปพลิเคชันของคุณหรือการทดสอบหน่วย Runtime Dependency จะถูกคัดลอกลงในแอปพลิเคชันที่คุณปรับใช้ แต่จะไม่สามารถใช้งานได้ในระหว่างการคอมไพล์! นี่เป็นสิ่งที่ดีสำหรับการตรวจสอบว่าคุณไม่ได้ขึ้นอยู่กับไลบรารีเฉพาะอย่างผิดพลาด

สุดท้ายขอบเขตที่ระบุระบุว่าคอนเทนเนอร์ที่แอปพลิเคชันของคุณดำเนินการนั้นให้การพึ่งพาในนามของคุณ ในแอ็พพลิเคชัน Java EE หมายความว่าการอ้างอิงนั้นมีอยู่แล้วบนคลาสพา ธ ของเซิร์ฟเวอร์ Servlet หรือแอ็พพลิเคชันเซิร์ฟเวอร์และจะไม่ถูกคัดลอกลงในแอปพลิเคชันที่ปรับใช้ของคุณ นอกจากนี้ยังหมายความว่าคุณต้องการการพึ่งพานี้เพื่อรวบรวมโครงการของคุณ


@Koray Tugay คำตอบนั้นแม่นยำกว่า :) ฉันมีคำถามสั้น ๆ ว่าฉันมีโถที่พึ่งพาพร้อมขอบเขตของเวลาทำงาน maven จะมองหา jar ในเวลารวบรวมหรือไม่?
gks

@gks ไม่มันไม่ต้องการมันในเวลาคอมไพล์
Koray Tugay

9

คุณต้องใช้เวลาในการรวบรวมการอ้างอิงซึ่งคุณอาจต้องการในขณะรันไทม์ อย่างไรก็ตามไลบรารีจำนวนมากทำงานโดยไม่มีการอ้างอิงที่เป็นไปได้ทั้งหมด นั่นคือไลบรารีที่สามารถใช้ไลบรารี XML ที่แตกต่างกันสี่ไลบรารี แต่ต้องการเพียงหนึ่งไลบรารีเพื่อทำงาน

ห้องสมุดจำนวนมากจำเป็นต้องมีห้องสมุดอื่น ๆ ไลบรารีเหล่านี้ไม่จำเป็นต้องใช้ในเวลาคอมไพล์ แต่จำเป็นสำหรับรันไทม์ กล่าวคือเมื่อรหัสถูกเรียกใช้จริง


คุณช่วยยกตัวอย่างไลบรารีดังกล่าวที่ไม่จำเป็นในการคอมไพล์ แต่จำเป็นต้องใช้ในรันไทม์ได้ไหม
Cristiano

1
@Cristiano ห้องสมุด JDBC ทั้งหมดเป็นแบบนี้ ไลบรารีที่ใช้ API มาตรฐาน
Peter Lawrey

4

โดยทั่วไปคุณพูดถูกและน่าจะเป็นสถานการณ์ที่ดีที่สุดหากการอ้างอิงเวลารันไทม์และเวลาคอมไพล์เหมือนกัน

ฉันจะให้คุณ 2 ตัวอย่างเมื่อกฎนี้ไม่ถูกต้อง

ถ้าคลาส A ขึ้นอยู่กับคลาส B ซึ่งขึ้นอยู่กับคลาส C ซึ่งขึ้นอยู่กับคลาส D โดยที่ A คือคลาสของคุณและ B, C และ D เป็นคลาสจากไลบรารีของบุคคลที่สามที่แตกต่างกันคุณต้องการเพียง B และ C ในเวลาคอมไพล์และคุณต้อง D ด้วย รันไทม์ บ่อยครั้งที่โปรแกรมใช้การโหลดคลาสแบบไดนามิก ในกรณีนี้คุณไม่จำเป็นต้องโหลดคลาสแบบไดนามิกโดยไลบรารีที่คุณใช้ในเวลาคอมไพล์ ยิ่งไปกว่านั้นไลบรารีมักจะเลือกการนำไปใช้งานที่รันไทม์ ตัวอย่างเช่น SLF4J หรือ Commons Logging สามารถเปลี่ยนการนำบันทึกเป้าหมายไปใช้ที่รันไทม์ คุณต้องใช้ SSL4J เท่านั้นในเวลาคอมไพล์

ตัวอย่างตรงข้ามเมื่อคุณต้องการการอ้างอิงในเวลาคอมไพล์มากกว่าที่รันไทม์ คิดว่าคุณกำลังพัฒนาแอปพลิเคชันที่ต้องทำงานในสภาพแวดล้อมหรือระบบปฏิบัติการที่แตกต่างกัน คุณต้องการไลบรารีเฉพาะแพลตฟอร์มทั้งหมดในเวลาคอมไพล์และเฉพาะไลบรารีที่จำเป็นสำหรับสภาพแวดล้อมปัจจุบันที่รันไทม์

ฉันหวังว่าคำอธิบายของฉันจะช่วยได้


คุณสามารถอธิบายรายละเอียดว่าทำไมจึงต้องใช้ C ในเวลารวบรวมในตัวอย่างของคุณ ฉันได้รับความประทับใจ (จากstackoverflow.com/a/7257518/6095334 ) ว่าจะต้องใช้ C หรือไม่ในเวลาคอมไพล์ขึ้นอยู่กับวิธีการและฟิลด์ใด (จาก B) A อ้างอิง
Hervian

3

โดยปกติแล้วการอ้างอิงคงกราฟย่อยกราฟของแบบไดนามิกหนึ่งเห็นเช่นรายการบล็อกนี้จากการเขียนของ NDepend

ที่กล่าวว่ามีข้อยกเว้นบางประการซึ่งส่วนใหญ่เป็นการอ้างอิงที่เพิ่มการสนับสนุนคอมไพเลอร์ซึ่งจะมองไม่เห็นในรันไทม์ ยกตัวอย่างเช่นสำหรับการสร้างรหัสผ่านทางลอมบอกหรือการตรวจสอบเพิ่มเติมตามทาง(TYPE- pluggable) ตรวจสอบกรอบ


2

เพิ่งพบปัญหาที่ตอบคำถามของคุณ servlet-api.jarเป็นการพึ่งพาชั่วคราวในโครงการเว็บของฉันและจำเป็นทั้งในเวลาคอมไพล์และรันไทม์ แต่servlet-api.jarยังรวมอยู่ในห้องสมุด Tomcat ของฉันด้วย

วิธีแก้ปัญหาคือทำให้servlet-api.jarใน maven พร้อมใช้งานในเวลาคอมไพล์เท่านั้นและไม่รวมอยู่ในไฟล์ war ของฉันเพื่อที่จะไม่ปะทะกับไฟล์ที่servlet-api.jarมีอยู่ในไลบรารี Tomcat ของฉัน

ฉันหวังว่านี่จะอธิบายถึงเวลาคอมไพล์และการพึ่งพารันไทม์


3
ตัวอย่างของคุณเป็นจริงไม่ถูกต้องสำหรับคำถามที่ได้รับทำให้มันอธิบายความแตกต่างระหว่างcompileและprovidedขอบเขตและไม่ได้อยู่ระหว่างและcompile จำเป็นต้องใช้ในเวลารวบรวมและบรรจุในแอปของคุณ จำเป็นในเวลาคอมไพล์เท่านั้น แต่ไม่ได้รวมอยู่ในแอพของคุณเนื่องจากมีให้โดยหมายอื่นเช่นมีอยู่แล้วในเซิร์ฟเวอร์ Tomcat runtimeCompile scopeProvided scope
MJar

1
ดีฉันคิดว่านี่เป็นค่อนข้างดีเช่นเพราะคำถามคือเกี่ยวกับการรวบรวมเวลาและรันไทม์อ้างอิงและไม่เกี่ยวกับการcompileและผู้เชี่ยวชาญขอบเขตruntime providedขอบเขตเป็นวิธี Maven จับกรณีที่พึ่งพารวบรวมเวลาไม่ควรรวมอยู่ในแพคเกจรันไทม์
Christian Gawron

1

ฉันเข้าใจความแตกต่างระหว่างรันไทม์และเวลาคอมไพล์และวิธีแยกความแตกต่างระหว่างทั้งสอง แต่ฉันไม่เห็นว่าจำเป็นต้องสร้างความแตกต่างระหว่างการอ้างอิงเวลาคอมไพล์และรันไทม์

แนวคิดทั่วไปเกี่ยวกับเวลาคอมไพล์และรันไทม์และการอ้างอิงเฉพาะของ Maven compileและruntimeขอบเขตเป็นสองสิ่งที่แตกต่างกันมาก คุณไม่สามารถเปรียบเทียบได้โดยตรงเนื่องจากสิ่งเหล่านี้ไม่มีเฟรมเดียวกัน: แนวคิดการคอมไพล์และรันไทม์ทั่วไปนั้นกว้างในขณะที่แนวคิดmaven compileและruntimeขอบเขตนั้นเกี่ยวกับความพร้อมใช้งาน / การมองเห็นที่อ้างอิงตามเวลา: การรวบรวมหรือการดำเนินการ
อย่าลืมว่า Maven อยู่เหนือทั้งหมดjavac/ javaเสื้อคลุมและใน Java คุณมี classpath รวบรวมเวลาที่คุณระบุมีjavac -cp ... และ classpath java -cp ...รันไทม์ที่คุณระบุด้วย
ไม่ผิดที่จะพิจารณาcompileขอบเขตMaven เป็นวิธีเพิ่มการพึ่งพาทั้งใน Java compile และ runtime classppath (javacและjava) ในขณะที่runtimeขอบเขตMaven สามารถมองเห็นได้ว่าเป็นวิธีเพิ่มการพึ่งพาเฉพาะใน Java runtime classppath ( javac)

สิ่งที่ฉันสำลักคือ: โปรแกรมจะไม่ขึ้นอยู่กับบางสิ่งบางอย่างในรันไทม์ที่ขึ้นอยู่ระหว่างการคอมไพล์ได้อย่างไร

สิ่งที่คุณอธิบายไม่มีความสัมพันธ์runtimeและcompileขอบเขตใด ๆ
ดูเหมือนprovidedว่าขอบเขตที่คุณระบุสำหรับการอ้างอิงจะขึ้นอยู่กับขอบเขตนั้นในเวลาคอมไพล์ แต่ไม่ใช่ที่รันไทม์
คุณใช้มันตามที่คุณต้องการการอ้างอิงในการคอมไพล์ แต่คุณไม่ต้องการรวมไว้ในคอมโพเนนต์แบบแพ็กเกจ (JAR, WAR หรืออื่น ๆ ) เนื่องจากการอ้างอิงนั้นจัดเตรียมไว้แล้วโดยสภาพแวดล้อม: สามารถรวมไว้ในเซิร์ฟเวอร์หรือใด ๆ พา ธ ของคลาสพา ธ ที่ระบุเมื่อแอ็พพลิเคชัน Java เริ่มทำงาน

หากแอป Java ของฉันใช้ log4j แสดงว่าต้องใช้ไฟล์ log4j.jar เพื่อที่จะคอมไพล์ (รหัสของฉันที่รวมเข้ากับและเรียกใช้เมธอดสมาชิกจากภายใน log4j) รวมทั้งรันไทม์ (รหัสของฉันไม่สามารถควบคุมสิ่งที่เกิดขึ้นได้อย่างแน่นอนเมื่อโค้ดภายใน log4j .jar รัน)

ในกรณีนี้ใช่ แต่สมมติว่าคุณต้องเขียนโค้ดแบบพกพาที่อาศัย slf4j เป็นส่วนหน้าของ log4j เพื่อให้สามารถเปลี่ยนไปใช้การบันทึกอื่นในภายหลัง (log4J 2, logback หรืออื่น ๆ )
ในกรณีนี้ในคุณ pom คุณต้องระบุ slf4j เป็นการcompileอ้างอิง (เป็นค่าเริ่มต้น) แต่คุณจะระบุการอ้างอิง log4j เป็นการruntimeอ้างอิง:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>...</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>...</version>
    <scope>runtime</scope>
</dependency>

ด้วยวิธีนี้คลาส log4j ไม่สามารถอ้างอิงในโค้ดที่คอมไพล์ได้ แต่คุณจะยังคงสามารถอ้างถึงคลาส slf4j ได้
หากคุณระบุการอ้างอิงทั้งสองด้วยcompileเวลาจะไม่มีสิ่งใดขัดขวางคุณจากการอ้างอิงคลาส log4j ในโค้ดที่คอมไพล์และคุณสามารถสร้างการเชื่อมต่อที่ไม่พึงปรารถนากับการใช้งานการบันทึก:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>...</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>...</version>
</dependency>

การใช้runtimeขอบเขตทั่วไปคือการประกาศการอ้างอิง JDBC ในการเขียนโค้ดแบบพกพาคุณไม่ต้องการให้โค้ดไคลเอ็นต์อ้างถึงคลาสของการพึ่งพา DBMS ที่เฉพาะเจาะจง (ตัวอย่างเช่น PostgreSQL JDBC dependency) แต่คุณต้องการให้สิ่งเดียวกันทั้งหมดรวมไว้ในแอปพลิเคชันของคุณในขณะรันไทม์คลาสจำเป็นในการสร้าง JDBC API ทำงานกับ DBMS นี้


0

ในเวลาคอมไพล์คุณเปิดใช้งานสัญญา / API ที่คุณคาดหวังจากการอ้างอิงของคุณ (เช่นที่นี่คุณเพิ่งเซ็นสัญญากับผู้ให้บริการอินเทอร์เน็ตบรอดแบนด์) ในขณะทำงานจริงคุณกำลังใช้การอ้างอิง (เช่นที่นี่คุณกำลังใช้อินเทอร์เน็ตบรอดแบนด์จริงๆ)


0

เพื่อตอบคำถาม "โปรแกรมจะไม่ขึ้นอยู่กับบางสิ่งในรันไทม์ที่มันขึ้นอยู่ระหว่างการคอมไพล์ได้อย่างไร" ลองดูตัวอย่างของตัวประมวลผลคำอธิบายประกอบ

สมมติว่าคุณเขียนหน่วยประมวลผลคำอธิบายประกอบของคุณเองและสมมติว่ามีการอ้างอิงเวลาคอมไพล์com.google.auto.service:auto-serviceเพื่อให้สามารถใช้งาน@AutoServiceได้ การอ้างอิงนี้จำเป็นสำหรับการคอมไพล์ตัวประมวลผลคำอธิบายประกอบเท่านั้น แต่ไม่จำเป็นต้องใช้ในรันไทม์: โปรเจ็กต์อื่น ๆ ทั้งหมดขึ้นอยู่กับตัวประมวลผลคำอธิบายประกอบของคุณสำหรับการประมวลผลคำอธิบายประกอบไม่ต้องการการพึ่งพาcom.google.auto.service:auto-serviceที่รันไทม์ (หรือในเวลาคอมไพล์หรือในเวลาอื่น ๆ ) .

นี่ไม่ใช่เรื่องธรรมดา แต่มันเกิดขึ้น


0

runtimeขอบเขตจะมีการป้องกันไม่ให้โปรแกรมเมอร์จากการเพิ่มการอ้างอิงโดยตรงกับการดำเนินงานห้องสมุดในรหัสแทนการใช้แนวคิดหรือfaçades

กล่าวอีกนัยหนึ่งคือบังคับให้ใช้อินเทอร์เฟซ

ตัวอย่างที่เป็นรูปธรรม:

1) ทีมของคุณใช้ SLF4J ผ่าน Log4j คุณต้องการให้โปรแกรมเมอร์ของคุณใช้ SLF4J API ไม่ใช่ Log4j Log4j ถูกใช้โดย SLF4J ภายในเท่านั้น สารละลาย:

  • กำหนด SLF4J เป็นการพึ่งพาเวลาคอมไพล์ปกติ
  • กำหนด log4j-core และ log4j-api เป็นการพึ่งพารันไทม์

2) แอปพลิเคชันของคุณกำลังเข้าถึง MySQL โดยใช้ JDBC คุณต้องการให้โปรแกรมเมอร์เขียนโค้ดเทียบกับนามธรรม JDBC มาตรฐานไม่ใช่เทียบกับการใช้งานไดรเวอร์ MySQL โดยตรง

  • กำหนดmysql-connector-java(ไดรเวอร์ MySQL JDBC) เป็นการพึ่งพารันไทม์

การอ้างอิงรันไทม์ถูกซ่อนไว้ในระหว่างการคอมไพล์ (การโยนข้อผิดพลาดเวลาคอมไพล์หากโค้ดของคุณมีการพึ่งพา "โดยตรง") แต่จะรวมอยู่ในช่วงเวลาดำเนินการและเมื่อสร้างอาร์ติแฟกต์ที่ปรับใช้ได้ (ไฟล์ WAR, ไฟล์ jar SHADED ฯลฯ )

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.