โค้ดยิม/จาวาบล็อก/สุ่ม/AOP คืออะไร? หลักการเขียนโปรแกรมเชิงลักษณะ
John Squirrels
ระดับ
San Francisco

AOP คืออะไร? หลักการเขียนโปรแกรมเชิงลักษณะ

เผยแพร่ในกลุ่ม
สวัสดีพวกคุณ! หากไม่เข้าใจแนวคิดพื้นฐาน การเจาะลึกกรอบการทำงานและวิธีการสร้างฟังก์ชันการทำงานจึงค่อนข้างยาก ดังนั้นวันนี้เราจะพูดถึงแนวคิดดังกล่าว — AOP หรือที่เรียกว่าการเขียนโปรแกรมเชิงลักษณะ AOP คืออะไร?  หลักการเขียนโปรแกรมเชิงลักษณะ - 1หัวข้อนี้ไม่ง่ายและไม่ค่อยได้ใช้โดยตรง แต่เฟรมเวิร์กและเทคโนโลยีจำนวนมากใช้หัวข้อนี้ภายใต้ประทุน และแน่นอนว่าบางครั้งในระหว่างการสัมภาษณ์ คุณอาจถูกขอให้อธิบายโดยทั่วๆ ไปว่าสัตว์ร้ายชนิดนี้คืออะไรและนำไปใช้ได้ที่ไหน ลองมาดูแนวคิดพื้นฐานและตัวอย่างง่ายๆ ของAOP ใน Java ตอนนี้AOPย่อมาจากการเขียนโปรแกรมเชิงลักษณะซึ่งเป็นกระบวนทัศน์ที่มีจุดประสงค์เพื่อเพิ่มความเป็นโมดูลาร์ของส่วนต่าง ๆ ของแอปพลิเคชันโดยแยกข้อกังวลเกี่ยวกับการตัดขวาง เพื่อให้บรรลุเป้าหมายนี้ พฤติกรรมเพิ่มเติมจะถูกเพิ่มลงในรหัสที่มีอยู่โดยไม่ทำการเปลี่ยนแปลงรหัสเดิม กล่าวอีกนัยหนึ่ง เราสามารถคิดว่ามันเป็นการแขวนฟังก์ชันเพิ่มเติมไว้เหนือเมธอดและคลาสโดยไม่แก้ไขโค้ดที่แก้ไข เหตุใดจึงจำเป็น ไม่ช้าก็เร็ว เราสรุปได้ว่าแนวทางเชิงวัตถุทั่วไปไม่สามารถแก้ปัญหาบางอย่างได้อย่างมีประสิทธิภาพเสมอไป และเมื่อช่วงเวลานั้นมาถึงAOPก็เข้ามาช่วยเหลือและมอบเครื่องมือเพิ่มเติมสำหรับการสร้างแอปพลิเคชันให้กับเรา และเครื่องมือเพิ่มเติมหมายถึงความยืดหยุ่นที่เพิ่มขึ้นในการพัฒนาซอฟต์แวร์ ซึ่งหมายถึงตัวเลือกเพิ่มเติมสำหรับการแก้ปัญหาเฉพาะ

การสมัคร AOP

การเขียนโปรแกรมเชิงมุมมองได้รับการออกแบบให้ทำงานแบบตัดขวาง ซึ่งสามารถเป็นรหัสใดๆ ที่อาจทำซ้ำได้หลายครั้งด้วยวิธีการต่างๆ ซึ่งไม่สามารถจัดโครงสร้างเป็นโมดูลแยกต่างหากได้อย่างสมบูรณ์ ดังนั้นAOP จึง ช่วยให้เราเก็บสิ่งนี้ไว้นอกโค้ดหลักและประกาศในแนวตั้ง ตัวอย่างคือการใช้นโยบายความปลอดภัยในแอปพลิเคชัน โดยปกติแล้ว การรักษาความปลอดภัยจะทำงานผ่านองค์ประกอบหลายอย่างของแอปพลิเคชัน ยิ่งไปกว่านั้น นโยบายความปลอดภัยของแอปพลิเคชันควรนำไปใช้กับส่วนที่มีอยู่และส่วนใหม่ทั้งหมดของแอปพลิเคชันอย่างเท่าเทียมกัน ในขณะเดียวกัน นโยบายความปลอดภัยที่ใช้งานอยู่สามารถพัฒนาได้เอง นี่คือสถานที่ที่สมบูรณ์แบบสำหรับการใช้AOP อีกตัวอย่างหนึ่งคือการบันทึก. มีข้อดีหลายประการในการใช้วิธี AOP ในการบันทึกแทนที่จะเพิ่มฟังก์ชันการบันทึกด้วยตนเอง:
  1. รหัสสำหรับการบันทึกนั้นง่ายต่อการเพิ่มและลบ: ทั้งหมดที่คุณต้องทำคือเพิ่มหรือลบการกำหนดค่าบางอย่างของบางลักษณะ

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

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

    นอกจากนี้ เมื่อลบด้านออกจากการกำหนดค่าการออกแบบ คุณจะมั่นใจได้ว่าโค้ดการติดตามทั้งหมดหายไปและไม่มีอะไรหายไป

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

หลักการพื้นฐานของ AOP

หากต้องการก้าวต่อไปในหัวข้อนี้ เรามาทำความรู้จักกับแนวคิดหลักของ AOP กันก่อน คำแนะนำ — ตรรกะหรือรหัสเพิ่มเติมที่เรียกจากจุดรวม คำแนะนำสามารถดำเนินการก่อน หลัง หรือแทนการเข้าร่วม (เพิ่มเติมเกี่ยวกับสิ่งเหล่านี้ด้านล่าง) ประเภทของคำแนะนำที่เป็นไปได้:
  1. ก่อนหน้า — คำแนะนำประเภทนี้ถูกเรียกใช้ก่อนที่เมธอดเป้าหมาย เช่น จุดรวม จะถูกดำเนินการ เมื่อใช้คุณลักษณะเป็นคลาส เราจะใช้ คำอธิบาย ประกอบ @Beforeเพื่อทำเครื่องหมายคำแนะนำว่ามาก่อน เมื่อใช้ลักษณะเป็น ไฟล์ .ajนี่จะเป็นเมธอดbefore()

  2. After — คำแนะนำที่ดำเนินการหลังจากการดำเนินการของเมธอด (จุดร่วม) เสร็จสิ้น ทั้งในการดำเนินการปกติและเมื่อมีการโยนข้อยกเว้น

    เมื่อใช้คุณลักษณะเป็นคลาส เราสามารถใช้ คำอธิบายประกอบ @Afterเพื่อระบุว่านี่คือคำแนะนำที่ตามมา

    เมื่อใช้ลักษณะเป็น ไฟล์ .ajนี่คือเมธอดafter()

  3. After Returning — คำแนะนำนี้จะดำเนินการเฉพาะเมื่อวิธีการเป้าหมายเสร็จสิ้นตามปกติ โดยไม่มีข้อผิดพลาด

    เมื่อลักษณะต่างๆ แสดงเป็นคลาส เราสามารถใช้ คำอธิบาย ประกอบ @AfterReturningเพื่อทำเครื่องหมายคำแนะนำว่ากำลังดำเนินการหลังจากดำเนินการเสร็จสิ้น

    เมื่อใช้ลักษณะเป็น ไฟล์ .ajนี่จะเป็นเมธอดการคืนค่าหลัง () (Object obj)

  4. After Throwing — คำแนะนำนี้มีไว้สำหรับกรณีที่เมธอด เช่น join point โยนข้อยกเว้น เราสามารถใช้คำแนะนำนี้เพื่อจัดการกับการดำเนินการที่ล้มเหลวบางประเภท (เช่น เพื่อย้อนกลับธุรกรรมทั้งหมดหรือบันทึกด้วยระดับการติดตามที่จำเป็น)

    สำหรับแง่มุมของคลาส คำอธิบายประกอบ @AfterThrowingใช้เพื่อระบุว่าคำแนะนำนี้ใช้หลังจากโยนข้อยกเว้น

    เมื่อใช้ลักษณะเป็น ไฟล์ .ajนี่จะเป็นเมธอดafter() โยน (ยกเว้น e)

  5. รอบ ๆ - อาจเป็นหนึ่งในคำแนะนำที่สำคัญที่สุด มันล้อมรอบเมธอด นั่นคือ จุดรวมที่เราสามารถใช้ ตัวอย่างเช่น เลือกว่าจะดำเนินการเมธอดจุดรวมที่กำหนดหรือไม่

    คุณสามารถเขียนโค้ดคำแนะนำที่ทำงานก่อนและหลังการดำเนินการเมธอดจุดรวม

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

    ให้ลักษณะเป็นคลาส เราใช้ คำอธิบาย ประกอบ @Aroundเพื่อสร้างคำแนะนำที่ล้อมรอบจุดรวม เมื่อใช้ลักษณะต่างๆ ในรูปแบบ ไฟล์ .ajเมธอดนี้จะเป็นเมธอดaround()

จุดเชื่อมต่อ — จุดในโปรแกรมที่กำลังทำงานอยู่ (เช่น การเรียกใช้เมธอด การสร้างวัตถุ การเข้าถึงตัวแปร) ซึ่งควรใช้คำแนะนำ กล่าวอีกนัยหนึ่ง นี่คือนิพจน์ทั่วไปประเภทหนึ่งที่ใช้ในการค้นหาตำแหน่งสำหรับการแทรกโค้ด (ตำแหน่งที่ควรใช้คำแนะนำ) Pointcut — ชุดของจุดรวม pointcut กำหนดว่าคำแนะนำที่ได้รับนั้นใช้ได้กับจุดรวมที่กำหนดหรือไม่ Aspect — โมดูลหรือคลาสที่ใช้ฟังก์ชันตัดขวาง Aspect เปลี่ยนพฤติกรรมของโค้ดที่เหลือโดยใช้คำแนะนำที่จุดรวมที่กำหนดโดยpointcut กล่าวอีกนัยหนึ่งคือการรวมกันของคำแนะนำและจุดร่วม การแนะนำ— เปลี่ยนโครงสร้างของคลาสและ/หรือเปลี่ยนลำดับชั้นการสืบทอดเพื่อเพิ่มฟังก์ชันของลักษณะให้กับโค้ดต่างประเทศ เป้าหมาย — วัตถุที่จะใช้คำแนะนำ Weaving — กระบวนการเชื่อมโยงด้านต่างๆ กับวัตถุอื่นๆ เพื่อสร้างวัตถุพร็อกซีที่แนะนำ ซึ่งสามารถทำได้ในเวลาคอมไพล์ เวลาโหลด หรือรันไทม์ การทอมีสามประเภท:
  • คอมไพล์ไทม์เวฟ — ถ้าคุณมีซอร์สโค้ดของส่วนและรหัสที่คุณใช้ส่วนนั้น คุณสามารถคอมไพล์ซอร์สโค้ดและส่วนได้โดยตรงโดยใช้คอมไพเลอร์ AspectJ

  • การทอหลังการคอมไพล์ (การทอแบบไบนารี) — หากคุณไม่สามารถหรือไม่ต้องการใช้การแปลงซอร์สโค้ดเพื่อสานลักษณะต่างๆ ลงในโค้ด คุณสามารถใช้คลาสหรือไฟล์ jar ที่คอมไพล์ไว้ก่อนหน้านี้และใส่ลักษณะต่างๆ เข้าไปได้

  • การทอเวลาโหลด — นี่เป็นเพียงการทอแบบไบนารีที่ล่าช้าจนกว่าตัวโหลดคลาสจะโหลดไฟล์คลาสและกำหนดคลาสสำหรับ JVM

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

AspectJ — การใช้งานเฉพาะของ กระบวนทัศน์ AOPที่ใช้ความสามารถในการทำงานแบบตัดขวาง สามารถดูเอกสารได้ที่นี่

ตัวอย่างในภาษาจาวา

ต่อไป เพื่อความเข้าใจที่ดีขึ้นเกี่ยวกับAOPเราจะดูตัวอย่างรูปแบบ "Hello World" เล็กๆ ทางขวาของค้างคาว ฉันจะสังเกตว่าตัวอย่างของเราจะใช้ การคอมไพ ล์เวลาทอ ก่อนอื่น เราต้องเพิ่มการพึ่งพาต่อไปนี้ใน ไฟล์ pom.xml ของเรา :
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjrt</artifactId>
  <version>1.9.5</version>
</dependency>
ตามกฎแล้ว คอมไพเลอร์ ajc พิเศษ คือวิธีที่เราใช้ลักษณะต่างๆ IntelliJ IDEAไม่รวมไว้โดยค่าเริ่มต้น ดังนั้นเมื่อเลือกเป็นคอมไพเลอร์ของแอปพลิเคชัน คุณต้องระบุพาธไปยังการแจกจ่าย 5168 75 AspectJ นี่เป็นวิธีแรก ประการที่สองซึ่งเป็นสิ่งที่ฉันใช้คือการลงทะเบียนปลั๊กอินต่อไปนี้ใน ไฟล์ pom.xml :
<build>
  <plugins>
     <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>aspectj-maven-plugin</artifactId>
        <version>1.7</version>
        <configuration>
           <complianceLevel>1.8</complianceLevel>
           <source>1.8</source>
           <target>1.8</target>
           <showWeaveInfo>true</showWeaveInfo>
           <<verbose>true<verbose>
           <Xlint>ignore</Xlint>
           <encoding>UTF-8</encoding>
        </configuration>
        <executions>
           <execution>
              <goals>
                 <goal>compile</goal>
                 <goal>test-compile</goal>
              </goals>
           </execution>
        </executions>
     </plugin>
  </plugins>
</build>
หลังจากนี้ เป็นความคิดที่ดีที่จะนำเข้าจากMaven ใหม่และรันmvn clean compile ตอนนี้เรามาดำเนินการโดยตรงกับตัวอย่าง

ตัวอย่างที่ 1

มาสร้างMain class กัน เถอะ ในนั้น เราจะมีจุดเริ่มต้นและเมธอดที่พิมพ์ชื่อผ่านบนคอนโซล:
public class Main {

  public static void main(String[] args) {
  printName("Tanner");
  printName("Victor");
  printName("Sasha");
  }

  public static void printName(String name) {
     System.out.println(name);
  }
}
ไม่มีอะไรซับซ้อนที่นี่ เราส่งชื่อและแสดงบนคอนโซล หากเราเรียกใช้โปรแกรมตอนนี้ เราจะเห็นสิ่งต่อไปนี้บนคอนโซล:
แทนเนอร์ วิกเตอร์ ซาชา
ถึงเวลาแล้วที่จะใช้ประโยชน์จากพลังของ AOP ตอนนี้เราต้องสร้างไฟล์ภาพ มีสองประเภท: ประเภทแรกมีนามสกุลไฟล์ . aj คลาสที่สองคือคลาสธรรมดาที่ใช้คำอธิบายประกอบเพื่อใช้ความสามารถAOP ก่อนอื่นมาดูไฟล์ที่มี นามสกุล .aj :
public aspect GreetingAspect {

  pointcut greeting() : execution(* Main.printName(..));

  before() : greeting() {
     System.out.print("Hi, ");
  }
}
ไฟล์นี้เป็นเหมือนคลาส มาดูกันว่าเกิดอะไรขึ้นที่นี่: pointcutคือชุดของจุดรวม greeting()คือชื่อของ pointcut นี้ : การดำเนินการบ่งชี้ว่าจะใช้ระหว่างการดำเนินการเรียก ( * ) ทั้งหมดของเมธอดMain.printName(...) ถัดมาเป็นคำแนะนำเฉพาะ — before() — ซึ่งดำเนินการก่อนที่จะเรียกเมธอดเป้าหมาย : greeting()เป็นจุดตัดที่คำแนะนำนี้ตอบสนอง และด้านล่างเราจะเห็นเนื้อหาของวิธีการเองซึ่งเขียนด้วยภาษา Java ซึ่งเราเข้าใจ เมื่อเราเรียกใช้mainด้วยลักษณะนี้ เราจะได้เอาต์พุตคอนโซลนี้:
สวัสดี แทนเนอร์ สวัสดี วิคเตอร์ สวัสดี ซาชา
เราจะเห็นว่าทุกการเรียกใช้เมธอดprintNameได้รับการแก้ไขด้วยแง่มุม ทีนี้ลองมาดูกันว่าลักษณะของคลาส Java ที่มีคำอธิบายประกอบจะมีลักษณะอย่างไร:
@Aspect
public class GreetingAspect{

  @Pointcut("execution(* Main.printName(String))")
  public void greeting() {
  }

  @Before("greeting()")
  public void beforeAdvice() {
     System.out.print("Hi, ");
  }
}
หลังจาก ไฟล์ขนาด .ajทุกอย่างจะชัดเจนมากขึ้นที่นี่:
  • @Aspectระบุว่าคลาสนี้เป็นลักษณะ
  • @Pointcut("execution(* Main.printName(String))")เป็นจุดตัดที่เรียกใช้สำหรับการเรียกทั้งหมดไปยังMain.printNameด้วยอาร์กิวเมนต์อินพุตที่มีประเภทคือString ;
  • @Before("greeting()")เป็นคำแนะนำที่ใช้ก่อนที่จะเรียกรหัสที่ระบุในจุดตัดการทักทาย()
การรันmainด้วยลักษณะนี้จะไม่เปลี่ยนเอาต์พุตของคอนโซล:
สวัสดี แทนเนอร์ สวัสดี วิคเตอร์ สวัสดี ซาชา

ตัวอย่างหมายเลข 2

สมมติว่าเรามีเมธอดที่ดำเนินการบางอย่างสำหรับลูกค้า และเราเรียกเมธอดนี้จากmain :
public class Main {

  public static void main(String[] args) {
  performSomeOperation("Tanner");
  }

  public static void performSomeOperation(String clientName) {
     System.out.println("Performing some operations for Client " + clientName);
  }
}
ลองใช้ คำอธิบายประกอบ @Aroundเพื่อสร้าง "ธุรกรรมหลอก":
@Aspect
public class TransactionAspect{

  @Pointcut("execution(* Main.performSomeOperation(String))")
  public void executeOperation() {
  }

  @Around(value = "executeOperation()")
  public void beforeAdvice(ProceedingJoinPoint joinPoint) {
     System.out.println("Opening a transaction...");
     try {
        joinPoint.proceed();
        System.out.println("Closing a transaction...");
     }
     catch (Throwable throwable) {
        System.out.println("The operation failed. Rolling back the transaction...");
     }
  }
  }
ด้วย วิธี การดำเนินการของ วัตถุ ProceedingJoinPointเราเรียกวิธีการห่อเพื่อระบุตำแหน่งในคำแนะนำ ดังนั้นโค้ดในเมธอดด้านบนjoinPoint.proceed(); คือBeforeในขณะที่โค้ดด้านล่างคือAfter ถ้าเราเรียกใช้mainเราจะได้สิ่งนี้ในคอนโซล:
กำลังเปิดธุรกรรม... กำลังดำเนินการบางอย่างสำหรับ Client Tanner กำลังปิดธุรกรรม...
แต่ถ้าเราโยนและข้อยกเว้นในวิธีการของเรา (เพื่อจำลองการดำเนินการที่ล้มเหลว):
public static void performSomeOperation(String clientName) throws Exception {
  System.out.println("Performing some operations for Client " + clientName);
  throw new Exception();
}
จากนั้นเราจะได้เอาต์พุตคอนโซลนี้:
กำลังเปิดธุรกรรม... กำลังดำเนินการบางอย่างสำหรับ Client Tanner การดำเนินการล้มเหลว กำลังย้อนกลับธุรกรรม...
สิ่งที่เราลงเอยด้วยนี่คือความสามารถในการจัดการข้อผิดพลาดประเภทหนึ่ง

ตัวอย่างหมายเลข 3

ในตัวอย่างต่อไป เราจะทำบางอย่าง เช่น การเข้าสู่คอนโซล อันดับแรก ให้ดูที่Mainซึ่งเราได้เพิ่มตรรกะทางธุรกิจหลอก:
public class Main {
  private String value;

  public static void main(String[] args) throws Exception {
     Main main = new Main();
     main.setValue("<some value>");
     String valueForCheck = main.getValue();
     main.checkValue(valueForCheck);
  }

  public void setValue(String value) {
     this.value = value;
  }

  public String getValue() {
     return this.value;
  }

  public void checkValue(String value) throws Exception {
     if (value.length() > 10) {
        throw new Exception();
     }
  }
}
ในmainเราใช้setValueเพื่อกำหนดค่าให้กับตัวแปรอินสแตนซ์ของค่า จากนั้นเราใช้getValueเพื่อรับค่า แล้วเรียก checkValue เพื่อดูว่ามีความยาวเกิน 10 อักขระหรือไม่ หากเป็นเช่นนั้น ข้อยกเว้นจะถูกโยนทิ้งไป ทีนี้มาดูลักษณะที่เราจะใช้ในการบันทึกการทำงานของเมธอด:
@Aspect
public class LogAspect {

  @Pointcut("execution(* *(..))")
  public void methodExecuting() {
  }

  @AfterReturning(value = "methodExecuting()", returning = "returningValue")
  public void recordSuccessfulExecution(JoinPoint joinPoint, Object returningValue) {
     if (returningValue != null) {
        System.out.printf("Successful execution: method — %s method, class — %s class, return value — %s\n",
              joinPoint.getSignature().getName(),
              joinPoint.getSourceLocation().getWithinType().getName(),
              returningValue);
     }
     else {
        System.out.printf("Successful execution: method — %s, class — %s\n",
              joinPoint.getSignature().getName(),
              joinPoint.getSourceLocation().getWithinType().getName());
     }
  }

  @AfterThrowing(value = "methodExecuting()", throwing = "exception")
  public void recordFailedExecution(JoinPoint joinPoint, Exception exception) {
     System.out.printf("Exception thrown: method — %s, class — %s, exception — %s\n",
           joinPoint.getSignature().getName(),
           joinPoint.getSourceLocation().getWithinType().getName(),
           exception);
  }
}
เกิดอะไรขึ้นที่นี่? @Pointcut("execution(* *(..))")จะเข้าร่วมการโทรทุกวิธี @AfterReturning(value = "methodExecuting()", return = "returningValue")เป็นคำแนะนำที่จะดำเนินการหลังจากการดำเนินการตามวิธีการเป้าหมายสำเร็จ เรามีสองกรณีที่นี่:
  1. เมื่อเมธอดมีค่าตอบแทน — if (returningValue! = Null) {
  2. เมื่อไม่มีค่าส่งคืน — อื่น {
@AfterThrowing(value = "methodExecuting()", Throwing = "exception")เป็นคำแนะนำที่จะถูกทริกเกอร์ในกรณีที่เกิดข้อผิดพลาด นั่นคือ เมื่อเมธอดโยนข้อยกเว้น และด้วยการเรียกใช้mainเราจะได้รับการบันทึกตามคอนโซลประเภทหนึ่ง:
ดำเนินการสำเร็จ: เมธอด — setValue, คลาส — หลัก ดำเนินการสำเร็จ: เมธอด — getValue, คลาส — หลัก, ค่าส่งกลับ — <ค่าบางอย่าง> ข้อยกเว้นส่ง: เมธอด — checkValue, คลาส — ข้อยกเว้นหลัก — java.lang.Exception ข้อยกเว้นส่ง: เมธอด — หลัก, คลาส — หลัก, ข้อยกเว้น — java.lang.Exception
และเนื่องจากเราไม่ได้จัดการกับข้อยกเว้น เราจึงยังคงได้รับสแต็กเทรซ: AOP คืออะไร?  หลักการเขียนโปรแกรมเชิงลักษณะ-3คุณสามารถอ่านเกี่ยวกับข้อยกเว้นและการจัดการข้อยกเว้นได้ในบทความเหล่านี้: ข้อยกเว้นใน Javaและข้อยกเว้น: การจับและการจัดการ นั่นคือทั้งหมดสำหรับฉันในวันนี้ วันนี้เรามาทำความรู้จักกับAOPและคุณจะเห็นได้ว่าสัตว์ร้ายตัวนี้ไม่ได้น่ากลัวอย่างที่บางคนคิดว่ามันเป็น ลาก่อนทุกคน!
ความคิดเห็น
  • เป็นที่นิยม
  • ใหม่
  • เก่า
คุณต้องลงชื่อเข้าใช้เพื่อแสดงความคิดเห็น
หน้านี้ยังไม่มีความคิดเห็นใด ๆ