วันเสาร์ที่ 23 มกราคม พ.ศ. 2559

Spring part 10-1 Bean Scopes

>> ก่อนจะต่อกันที่เรื่องนี้ขอเพิ่มข้อสังเกตจากที่ได้ลองผิดลองถูกกับโปรเจ็กค์มานะครับ
- ถามว่า @ComponentScan ใช้เมื่อไร? เอ้ ชื่อของมันก็สื่ออยู่แล้วคือไว้สแกน component ต่างๆในโปรเจ็กค์ ได้แก่ @Component, @Service และ @Repository เป็นต้น
- ถามว่า @ComponentScan สำคัญอย่างไรกับ @Autowired จากที่ได้สังเกตหากโปรเจ็กค์ไม่ได้ใช้ @Component, @Service และ @Repository มันก็ไม่มีความหมายอะไรเลย คือไม่ต้องเขียนก็ได้ โดยที่ @Autowired ยังคงทำงานฉีดบีนได้ตามปกติ แต่มีข้อแม้ว่าเราต้อง config บีนให้ครบถ้วนนะครับ (จบแล้ว)

>> Bean Scopes หรือก็คือขอบเขตของน้องถั่ว (ดำ) haha ขออภัยครับ ผมหมายถึง scope ของจาวาบีน เท่าที่ทราบตอนนี้มี 5 ขอบเขต ได้แก่
- Singleton (ค่านี้เป็น default)
- Prototype
- Request
- Session
- Global
*** สามขอบเขตหลัง Request, Session, Global ใช้กับ spring web เท่านั้นครับ ตัวอย่างเช่น spring mvc

>> Singleton scope ค่านี้คือ default ขอบเขตของบีน หมายความว่า
- จะมีออบเจ็กต์บีนเกิดขึ้นภายใน spring container หรือใน context เพียง 1 ออบเจ็กต์เท่านั้น, จะเรียก new กี่ครั้งมันก็จะมีแค่ 1 ออบเจ็กต์
- เมื่อเรียกใช้ singleton scope หรือ @Scope("singleton") สำหรับวิธี configuration ด้วยจาวาจำต้องเพิ่มจาร์ AOP เข้ามาด้วยนะครับ (ซึ่งเราเอาเข้ามาแล้วเรียบร้อย spring-aop-4.2.4.RELEASE.jar)
- แต่ถ้าเรียกใช้ singleton scope หรือ scope="singleton" สำหรับวิธี configuration ด้วย XML ไม่จำเป็นต้องเพิ่มจาร์ AOP

>> ตัวอย่างต่อไปนี้แสดงให้เห็นว่า แม้กำหนดหรือไม่กำหนด singleton scope และเราขอออบเจ็กต์ service จาก spring มาถึงสามครั้ง ออบเจ็กต์ที่ได้คือออบเจ็กต์ตัวเดียวกันทั้งหมดครับ (สังเกตจากหมายเลข address เดียวกัน)


- แบบที่ไม่ระบุ singleton scope



- แบบที่ระบุ singleton scope


สรุปได้ว่าทั้งสองผลลัพธ์เหมือนกัน เพราะว่า singleton scope คือค่าโดยปริยาย (default) นั่นเองครับ

Spring part 9-2 Spring Annotation Configuration without XML

>> เพราะจาวาบีนคือพื้นฐานที่โปรเจ็กค์จำเป็นต้องมีเสมอ และ part ที่ผ่านมาได้แสดงให้เห็นว่าเราสามารถ configuration บีนทั้งหมดด้วยภาษาจาวา ใช่ครับ เรายังไม่ได้ใช้ autowire กันเลย

>> เพื่อนๆควรทราบว่า context จะมองหาบีนได้ก็ต้องใช้การสแกน ซึ่ง @ComponentScan คือคำตอบที่เราจะใช้แทนแอตทริบิวต์ component-scan ในไฟล์ applicationContext.xml ครับ (เพราะเราลบไฟล์นี้ทิ้งไปแล้วไงล่ะ หุหุ)

>> @ComponentScan ก็ให้ระบุชื่อ package ที่ต้องการเข้าไป (มันเป็นอาร์เรย์ของสตริงจึงต้องอยู่ในเครื่องหมาย { และ } หรือพื้นฐานการกำหนดค่าเริ่มต้นให้กับอาร์เรย์ของจาวานั่นแหละครับ)

>> สำหรับ @Autowired เจ้า spring จะเลือกทำงาน autowire by constructor หรือ by name หรือ by type โดยอัตโนมัติ

>> เพื่อทดสอบให้เห็นว่าบีนนั้นสำคัญขนาดไหน เราจะยังให้ context เรียกไปที่ service ที่ชื่อ bookService ซึ่งเราได้ประกาศชื่อนี้ไว้แล้วที่ไฟล์ AppConfiguration.java เอาล่ะครับ ให้เริ่มจากลบหรือ comment คำสั่งในไฟล์ BookServiceImpl.java ส่วนที่มีการประกาศใช้ออบเจ็กต์ repository ให้เป็นแบบนี้

private BookRepository repository;

แล้วใส่ autowire เข้าไปอย่างเคย

@Autowired
private BookRepository repository;

แหม~เพื่อนๆคงตอบผมว่ามันรันได้แน่นอน ก็เคยทำมาแล้วนี่ โดยมันจะอาศัย default constructor (constructor ที่เราไม่ได้เขียน) ในการสร้างออบเจ็กต์ แต่เมื่อรันดูจะปรากฏ error ดังนี้ครับ

BeanCreationException
Error creating bean with name 'bookService': Injection of autowired dependencies failed;

BookServiceImpl.repository; nested exception is NoSuchBeanDefinitionException

คือสแกนหา repository bean ไม่เจอ แน่นอนว่าไม่มีทางหาเจอได้เพราะเราไม่ได้นิยามไว้นี่ครับ แก้ไขอย่างไร? ก็กลับไปนิยามให้เรียบร้อย

ไฟล์ชื่อ AppConfiguration.java เพิ่ม

@Bean
public BookRepository getBookRepository() {
return new BookRepositoryImpl();
}

กลไกดังกล่าวนี้ spring จะถือ BookRepository ไว้ในมือก่อนโปรแกรมที่เรียกใช้จะทำงานเสียอีก เมื่อมีความต้องการใช้ไทป์นี้ spring ก็จะบอกกับพ่อบ้าน autowire ว่าจงสร้างออบเจ็กต์และฉีดมันแก่คุณผู้เรียก


>> ที่เหลือก็เป็นการใช้ autowire กับส่วนอื่น ได้แก่
- กับ constructor ก็ต้องเขียน constructor แบบที่ต้องการขึ้นมาเองด้วย
- กับ setter method ก็ต้องเขียน setter method แบบที่ต้องการขึ้นมาเองด้วย

>> by constructor หรือก็คือ constructor injection ก็เขียน constructor กับย้าย @Autowired มาวางไว้ที่มัน

- เป็นเหตุให้โค้ดบางส่วน error เพราะเราไปเปลี่ยนการรับค่าของมัน ก็จัดการ injection หรือฉีดตรงๆแบบนี้เลย (หัวเราะ) ไม่มีเวทมนตร์ใดหรอก โค้ดนี้แสนธรรมดา

- และผลลัพธ์ เย้!


>> by type หรือก็คือ setter injection ก็เขียน setter method ขึ้นมาแล้วย้าย @Autowired ไปวางไว้ที่มัน สำคัญคือใครไม่ลบ constructor ดังตัวอย่างข้างต้นนี้ออกก็ต้องเขียน default constructor ขึ้นมา ไม่งั้นเจอ error ซึ่งกรณีนี้ผมเลือกเขียนเพิ่มครับ

- แก้ไขไฟล์ bean configuration ด้วย ให้เป็นแบบนี้เลย

- ผลการรัน เย้!


>> เพื่อนๆครับหากเรา comment หรือลบบรรทัดที่ประกาศ repository bean ออกไปจากไฟล์ AppConfiguration.java ดังนี้

- สิ่งที่จะเกิดขึ้นคือ spring จะหา bean นี้ไม่เจอ

- แต่เราแก้ไขได้ครับ ด้วยการ injection มันผ่านความสามารถของ @ComponentScan กล่าวคือขอให้ spring สแกนหาก่อนว่าประดาบีนที่เราต้องการนั้นอยู่ที่ไหน นี่จึงกลายเป็นความจำเป็นที่เราต้องใช้ @Component มาช่วยระบุคลาสใดๆที่เราต้องการให้มันเตรียมหรือถือไว้ในมือก่อน นอกจากนี้เรายังจะระบุความเป็น component ของมันให้ชัดเจนขึ้นตามระดับของ layer ดังที่เพื่อนๆทราบมาแล้ว
- รูปด้านล่างนี้แสดงให้เห็นว่า @Repository คือความชัดเจนของระดับ repository layer หรือก็คือ component ตัวหนึ่งที่เราต้องการบอกแก่ spring ครับผม

- ทดสอบการรัน

Spring part 9-1 Spring Annotation Configuration without XML

>> ในที่สุดก็เขียนจนมาถึงการ configuration ประดา bean โดยไม่ต้องใช้ไฟล์ XML แล้วนะครับ จากพื้นฐานเราทราบว่า spring จะฉีด bean ทั้งหลายให้กับคลาสที่เรียกใช้โดยมีคุณ autowire เป็นพ่อบ้านจัดการความต้องการนี้ให้

>> ในเมื่อทราบกันขนาดนี้แล้ว เราก็จะย้ายการนิยาม bean ต่างๆในไฟล์ applicationContext.xml ไปไว้กับโค้ดจาวาแทน เย้ๆ

>> ถามว่าทำไปทำไม?
ตอบว่า อยากหนี xml แล้วไปใช้ java annotation แทนไงล่ะ จะได้เขียน xml น้อยลง โค้ดก็สะอาดขึ้น

>> ใช้อะไรเพิ่มบ้างล่ะ?
ตอบว่า ครับผม มีดังนี้
- เราจะแทนที่ applicationContext.xml ด้วยไฟล์จาวา ให้ชื่อเดียวกันหรือต่างกันก็ได้ ในที่นี้เอาเป็นชื่อ AppConfiguration.java ก็แล้วกัน

- ใช้ @Configuration annotation มาจัดการความเป็น context หรือก็คือให้ไฟล์ AppConfiguration.java เป็นผู้รับผิดชอบหน้าที่ที่ไฟล์ applicationContext.xml เคยทำ (มันจะเป็นที่ประกาศหรือนิยาม bean ต่างๆ) ดังนั้น annotation นี้จึงอยู่ระดับคลาส

- ใช้ @Bean annotation เพื่อบอกว่าเหล่าเมธอด getter ที่กำลังจะนิยามขึ้นนี้คือ bean โดยจะตั้งชื่อให้หรือไม่ก็ได้อยู่ที่ว่าต้องการเรียกใช้มันด้วยชื่อหรือเปล่า (ซึ่งตัวอย่างนี้ใช้ครับ) ดังนั้น annotation นี้จึงอยู่ระดับเมธอด

*** ชื่อที่เราตั้งให้กับ annotation ไม่ว่าจะระดับคลาสหรือเมธอด spring ไม่สนใจว่าจะเป็น case sensitive หรือไม่ รู้เพียงว่าเป็นแค่สตริง

>> แล้วเขียนคลาสทดสอบอย่างไรเอ่ย?
ตอบว่า ตามที่กล่าวมา
- เราจะสร้าง AppConfiguration.java ไว้ที่ package
com.pros.example.server (ทั้งหมดอยู่ในรูปภาพ)

- เดิมเราเรียก context จากออบเจ็กต์ที่ชื่อ ClassPathXmlApplicationContext ก็ให้เปลี่ยนเป็น AnnotationConfigApplicationContext แล้วระบุเจ้า AppConfiguration.class เป็นพารามิเตอร์

- อย่าลืมลบไฟล์ applicationContext.xml ด้วยล่ะ เพราะไม่จำเป็นต้องใช้แล้ว จากนั้นคลิกขวาเลือก Run As ตามด้วย Java Application ได้เลย

>> และนี่คือ source code ครับ




วันจันทร์ที่ 18 มกราคม พ.ศ. 2559

Spring part 8-2 Spring Annotation Configuration with XML

ต่อจากคราวก่อนที่เรากล่าวถึง Stereotype Annotations, เขาคือผู้ช่วยที่จะทำให้โค้ดฝั่ง XML น้อยลงและเพิ่มโค้ดฝั่งจาวาเพียงเล็กน้อยเท่านั้นผ่านสิ่งที่เรียกว่า annotation ถามว่าสถานที่หรือ layer เช่นไรควรจะวาง @Component หรือวาง @Service หรือวาง @Repository? อ่านตอนท้ายของ part ที่ผ่านมาเรายังสามารถตอบได้ แต่ถ้าถามว่ามันให้ความเจาะจงหรือมีประโยชน์ยิ่งในเรื่องใดจึงต้องมาแบ่งมันออกตาม layer?

เท่าที่ผมทราบมาเขาว่ามันเป็นมากกว่านั้น เป็นมากกว่าการจัดเตรียมและฉีด (injection) ออบเจ็กต์เสียอีก เริ่มจากการแบ่งโค้ดออกเป็น layer จะช่วยให้เพื่อนๆจัดการโค้ดง่ายขึ้น มีสัดส่วนที่อธิบายหน้าที่ของมันอย่างชัดเจน และเมื่อนำ spring stereotype annotations มาใช้กับประดา layer ข้างต้น จะเป็นเหตุให้เราสามารถนำความคิด AOP (Aspect-oriented programming) มาใช้ต่อได้ ซึ่งหนึ่งในเป้าหมายก็คือการทำ pointcut ครับผม (อ่านเอกสาร) แต่ผมไม่ได้ศึกษาเรื่อง AOP ก็ยังคงนำมาเล่าให้ฟังไม่ได้ เอาล่ะ เรามาต่อที่โปรเจ็กค์คราวก่อนกันเถอะ

*** เพื่อนๆควรทราบว่าการไม่ระบุ configure namespaces แก่ spring bean configuration file (applicationContext.xml) เราก็จะไม่สามารถเรียกไปยังคลาสใดๆที่ต้องการได้ ดังขั้นตอนที่ผ่านมานี้ซึ่งเราได้บอกให้ spring bean configuration file รู้จักกับ beans และ context XSD namespaces (อ่านเอกสารว่ามันสำคัญอย่างไร) และด้วยวิธีการนี้ก็เพียงพอแล้วที่ spring จะรับรู้ว่าต่อไปนี้จะมีการใช้ annotation-config ภายในโปรเจ็กต์ พร้อมด้วยการกำหนดพื้นที่ที่จะให้มันมองหาเหล่า annotation ดังกล่าว

>> BookRepositoryImpl นั้นอยู่ใน repository layer เราจึงนำ @Repository ไปวางไว้ ดังนี้ (ยังไม่ต้องตั้งชื่อให้กับมันเหมือนในรูปด้านล่างก็ได้นะครับ เพราะเรายังไม่ได้ใช้)


>> ส่วน BookServiceImpl นั้นอยู่ใน service layer เราจึงนำ @Service ไปวางไว้ ดังนี้ (ตั้งชื่อด้วย เดี๋ยวจะเรียกใช้ที่ main)


>> กลับมาที่ main คลาส Program ครับ เขียนโค้ดทดสอบการเรียกใช้ service ผ่าน context กันเลย

*** จากจาร์ที่เรามี รันปุ๊บต้องพังทันที ให้เพิ่ม spring-aop จาร์เข้าไปอีกตัวครับ

*** โหลดจาก http://mvnrepository.com

>> จาร์ที่โหลดทั้งหมดมีดังนี้
- commons-logging-1.2.jar
- spring-aop-4.2.4.RELEASE.jar
- spring-beans-4.2.4.RELEASE.jar
- spring-context-4.2.4.RELEASE.jar
- spring-core-4.2.4.RELEASE.jar
- spring-expression-4.2.4.RELEASE.jar

>> เสร็จแล้วรันด้วยการคลิกขวาที่คลาส Program แล้วเลือก Run As เลือก Java Application


>> โปรเจ็กค์นี้เพื่อนๆจะสังเกตได้ว่า แท้จริงเวทมนตร์ของ spring นั้นถูกซ้อนเร้นจากสายตาคล้ายก้อนภูเขาน้ำแข็งใต้น้ำทะเลมิผิดเพี้ยน ระบบของมันเริ่มตั้งแต่การ bootstrap สิ่งที่เรียกว่า annotation scanner ในไฟล์ applicationContext.xml ที่เราได้ประกาศเอาไว้ กระทั่งเราสั่งให้ context เสาะหาชื่อที่ตั้งไว้ว่า bookService ในคลาส Program เจ้า context ก็จะสร้างออบเจ็กต์ของ BookService ให้กับเรา ถึงตอนนี้เราเรียกไปยังเมธอด findAll มันก็จะเข้าไปทำงานและคืนค่าออกมาเป็น List ของ Book นั่นเอง

>> ยังไม่น่าสนใจมากพอเพราะเราต่างรู้จัก Autowire จริงไหม? แล้วไหนล่ะการฉีดแบบไม่พึ่งการเขียน XML configuration?

>> เพื่อนๆทราบอยู่แล้วว่า autowire คือการฉีดออบเจ็กต์ใดๆให้กับคลาสที่ต้องการใช้ออบเจ็กต์นั้น และมีอยู่ 3 แห่งที่เราสามารถเขียน @Autowired ลงไปได้
1. Member variable
       ตัวอย่าง @Autowired private BookRepository bookRepository;

2. Constructor
       ตัวอย่าง @Autowired public BookServiceImpl( ... ) { ... }

3. Setter method
       ตัวอย่าง @Autowired public void setBookRepository( ... ) { ... }

>> เลือกอันแรกก่อนเลย autowire ผ่าน member variable ด้วยการลบหรือ comment คำสั่งให้ค่าที่เขียนว่า new BookRepositoryImpl(); ออกไป (ดูรูปประกอบนะครับ) แล้วรัน

- พังสิครับ เพราะค่าของออบเจ็กต์ repository เป็น null ไปแล้ว, โอเคนะ ใส่เวทมนตร์ได้ (ใส่ @Autowired)

- สำเร็จ!

>> เลือกอันที่สอง autowire ผ่าน constructor จึงต้องเขียน constructor ให้กับคลาส BookServiceImpl เพื่อทดสอบดังนี้

- สำเร็จ!

>> ข้อสุดท้ายแล้ว autowire ผ่าน setter method จึงต้องเขียน setter ให้กับคลาส BookServiceImpl เพื่อทดสอบดังนี้

- ปรากฏว่าพัง... เพราะมันหา default constructor ไม่เจอ และที่ไม่เจอก็เพราะว่าเราได้เขียน constructor ขึ้นมาเอง เป็นเหตุให้ default constructor ตายไปแล้วเรียบร้อย จะแก้ไขอย่างไรล่ะ? ก็เขียน constructor ที่มีหน้าตาเหมือน default constructor ขึ้นมาเพิ่มอีกสิ หรือไม่ก็ลบ constructor ที่มีอยู่ทิ้งไป ในที่นี้ผมเลือกเขียนขึ้นมาเพิ่มแล้วกันนะครับ

- สำเร็จ! และจากความรู้ที่ผ่านมาทำให้เราทราบว่าการ autowire ผ่าน setter method ในตัวอย่างนี้เป็นการ autowire by type เช่นเดียวกับตัวอย่างที่เคยใช้ xml เขียนมาแล้วนั่นเองครับ

วันอาทิตย์ที่ 17 มกราคม พ.ศ. 2559

Spring part 8-1 Spring Annotation Configuration with XML

>> ทบทวนกันสักเล็กน้อยว่าเราเดินทางมาถึงไหนแล้ว

- เรามีจาวาโค้ดที่คุยกันผ่าน interface, ด้วย interface คือกติกาหรือข้อกำหนดพฤติกรรมที่คลาส implement ทุกตัวจะต้องรับเอาไปเขียนให้เกิดการทำงานจริงๆ

- เราแบ่ง layer ของโปรแกรมออกเป็น server, service และ repository โดยกำหนดว่า

- server layer คือ back-end ที่จะถูกเรียกให้ทำงานเป็นอันดับแรกก่อน service layer และ repository layer

- service layer คือ บริการ ที่ทำหน้าที่ทาง business logic หรืองานจริงๆที่จะเกิดขึ้น

- repository layer คือ ชั้นที่ถูกแบ่งออกมาเพื่อกระทำกับข้อมูลที่ยังไม่เข้าข่าย business logic เช่น ติดต่อกับ database หรือ web-service เป็นต้น

- และยังมี model layer ที่กล่าวได้ว่าเป็น shared model ให้กับประดา layer ต่างๆข้างต้นเรียกไปใช้ โดยเน้นย้ำว่า model นี้จะต้องใช้จาวาคลาสอย่างธรรมดาที่สุดมาอธิบายความเป็นออบเจ็กต์ใดๆซึ่งเราเรียกว่า POJO

- ในงานจริงๆ ออบเจ็กต์จะถูกสร้างขึ้นจำนวนมาก ถูกกำหนดค่าให้ผ่านทาง constructor ก็ได้ ผ่านทาง setter method ก็ได้ ซึ่งงานลักษณะนี้ไม่ใช่ business อย่างแท้จริง

- จึงให้ spring framework ทำงาน configuration ดังข้างต้นผ่านทาง XML โดยให้มันจัดเตรียมออบเจ็กต์ที่ต้องการพร้อมกับกำหนดค่าให้ออบเจ็กต์

- และเมื่อถึงเวลาที่จาวาโค้ดทำงาน, spring จึงมีหน้าที่ฉีดออบเจ็กต์ที่ได้จัดเตรียมไว้นี้เพื่อทำงาน business นั่นเองครับ

- อย่างที่ได้เข้าใจกัน สสารไม่หายไปไหน เมื่อนำโค้ดฝั่งจาวาส่วนที่เป็นการจัดเตรียมออบเจ็กต์ออกไป ก็จะเพิ่มโค้ดฝั่ง XML เป็นเงาตามตัว เรียกได้ว่ายิ่งโค้ดฝั่งจาวาสะอาดเท่าไร โค้ดฝั่ง XML ก็จะสกปรกมากขึ้นเท่านั้น (คือเยอะขึ้น)

- และหากจะให้โค้ดฝั่ง XML สะอาดบ้าง หรือแตะ XML ให้น้อยที่สุด แน่นอนก็ต้องกลับมาเขียนโค้ดฝั่งจาวาเพิ่ม แต่จะเป็นการเพิ่มเพียงเล็กน้อยที่ยังดูสบายตา ทั้งยังบริหารจัดการง่ายดาย สิ่งนี้ในหัวข้อนี้ก็คือ Spring Annotation ครับ


>> Spring Annotation Configuration ผ่านทาง XML

- ยังคงต้องมี applicationContext.xml เช่นเดิม เพื่อประกาศ bean หรือจัดเตรียมออบเจ็กต์ใดๆที่รอฉีดให้แก่จาวาโค้ด (bean ก็คือ POJO ที่มีข้อกำหนดเพิ่มเติมเพียงแค่นิดหน่อย)

- เราจะเพิ่ม annotation scanner เข้ามาด้วย เพื่อให้ context สามารถตามหาคลาสใดๆ (ที่เป็น @Component, @Service, @Repository และอื่นๆ) ผ่านทาง namespace หรือก็คือ package ที่กำหนด

- นอกจากนี้เรายังประกาศข้อกำหนดของ context ซึ่งก็คือแท็ก beans โดยผมแนะนำให้ใช้ IDE ที่ชื่อ spring-tool-suite แทน eclipse ธรรมดาครับ

- ดาวน์โหลด spring-tool-suit เวอร์ชันล่าสุดได้จาก https://spring.io/tools ครับ




- นั่นก็เพราะว่าเครื่องมือนี้รู้จัก spring framework ไม่ว่าจะเป็นเรื่อง XML จาวาโค้ดหรือแม้แต่ annotation ทุกตัวที่เกี่ยวข้องกับมัน


>> มาเริ่มต้นกันใหม่อีกครั้ง

- วางโครงสร้างกันก่อน ก็คล้ายกับโครงสร้างเดิมครับ คือมี server, service, repository และ model พร้อม folder ชื่อ libs ดังนี้


- ทีนี้มาลองให้ spring-tool-suit สร้าง applicationContext.xml ให้ (เพราะมันคือไฟล์สำคัญที่ spring จะมาอ่าน)




- อย่างที่ได้กล่าวไป เราต้องการเพิ่ม context namespace เข้าไปใน applicationContext.xml, จงสลับจากแท็บ Source เป็น Namespace

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


- ดังนั้นจงไปดาวน์โหลดจาร์ทั้งหมดนี้มาใส่ใน folder ชื่อ libs แล้ว add to build path เสียเรียบร้อย, เข้าใจว่าเดี๋ยวรายการต่างๆจะปรากฏขึ้นมาให้เลือก
*** หากว่าใส่จาร์เข้าไปแล้วไม่เห็นผลใดๆ (คือหน้าต่างดังข้างต้นยังว่างอยู่) ให้ลองคลิกขวาที่โปรเจ็กค์แล้วเลือก Close Project ก่อนจะดับเบิลคลิกเปิดโปรเจ็กค์นี้ใหม่ จึงจะเห็นเหมือนรูปด้านล่าง


- ให้คลิกเพิ่ม context เข้าไปครับ มันบอกว่าจะเกิดการแก้ไขนะ ก็โอเคไป แล้วจึงสลับแท็บจาก Namespace เป็น Source



- ใช้ปุ่ม Ctrl + Spacebar เขียนสองแท็กต่อไปนี้ โดยกำหนดให้ component-scan รู้จัก base-package ของคลาสทั้งหมดของเราที่จะใช้ทำงาน สำหรับตัวอย่างนี้ก็เพื่อให้เข้าถึง server, service, repository และ model ได้ จึงกำหนดเป็น com.pros.example ครับผม


- ผมขออนุญาตใช้ตัวอย่างใหม่ที่ต่างจาก part ที่ผ่านมา โดยกำหนดให้คลาส Book เป็น model


- แต่ยังคงมี repository interface ในการค้นหาหนังสือทั้งหมด


- มี BookRepositoryImpl เป็นคลาสที่ implement เจ้า interface ข้างต้น

*** รายละเอียดของหนังสือตัวอย่างนำมาจาก https://www.packtpub.com

- แต่ยังคงมี service interface ในการค้นหาหนังสือทั้งหมด


- มี BookServiceImpl เป็นคลาสที่ implement เจ้า interface ข้างต้น


- และก็คลาส main ครับ



>> Stereotype Annotations

- ง่ายๆเลยนะครับ หลักๆที่จะใช้มีสามตัวได้แก่ @Component, @Service และ @Repository

- โดย @Service และ @Repository สืบทอดมาจากหรือขยายมาจาก @Component

- @Component ใช้กับ bean หรือ POJO ใดๆ

- @Service ใช้กับคลาสที่เกี่ยวข้องกับ business logic ถ้าอย่างใน spring mvc นั้นเราจะไม่เขียน business logic ไว้ใน controller หรอก แต่เราจะนำมาเขียนไว้ใน service แทนครับ

- @Repository ใช้กับคลาสที่เกี่ยวข้องกับ data ดังที่ได้เคยกล่าวไป เช่น เป็นชั้นของ dao หรือที่เรียกว่า database interaction layer เป็นต้น


>> ตอนนี้ดึกมากแล้ว และผมกำลังจะหลับ...zZ ไว้ต่อ part หน้านะครับ ฝันดีๆ