อะไรคือความแตกต่างระหว่างคำอธิบายประกอบ @Component, @Repository & @Service ใน Spring


2103

Can @Component, @Repositoryและ@Serviceคำอธิบายประกอบจะใช้สลับกันในฤดูใบไม้ผลิหรือพวกเขาไม่ให้การทำงานใด ๆ นอกเหนือจากการทำหน้าที่เป็นอุปกรณ์สัญกรณ์?

กล่าวอีกนัยหนึ่งถ้าฉันมีคลาสบริการและฉันเปลี่ยนคำอธิบายประกอบจาก@Serviceเป็น@Componentจะยังคงทำงานในลักษณะเดียวกันหรือไม่

คำอธิบายประกอบหรือไม่ก็มีผลต่อพฤติกรรมและการทำงานของชั้นเรียนหรือไม่


8
ในฐานะนักพัฒนาที่มีพื้นหลังของ Microsoft ฉันจำนิยามความหมายของบริการในกรอบงาน MS SmartClientSoftwareFactory แบบเก่า (ปัจจุบันเป็นกรอบซับซ้อนที่เลิกใช้งานมานานสำหรับแอพเดสก์ท็อปแบบกระจาย) คำจำกัดความนั้น (มีการบันทึกไว้อย่างดีโดย Rich Newman) กำหนดบริการเป็นวัตถุที่สามารถนำกลับมาใช้ใหม่ได้โดยเฉพาะอย่างยิ่งกับขอบเขต Singleton ที่ใช้ในการดำเนินการทางตรรกะทางธุรกิจกับวัตถุอื่นที่ส่งผ่านเป็นอาร์กิวเมนต์ ฉันมักจะดูบริการสปริงด้วยวิธีเดียวกัน
Ivaylo Slavov

3
ไม่เป็นไร !! อะไรก็ตามที่เหมาะกับคุณ :) ฉันเกลียดสิ่งนี้เสมอเกี่ยวกับ Spring ที่พวกเขามักจะกำหนด "กฎ" สำหรับคุณซึ่งเพิ่มคุณค่าเพียงเล็กน้อยให้กับใบสมัครของคุณ ไม่ต้องพูดถึงฤดูใบไม้ผลิมาพร้อมกับกองขนาดใหญ่ของตัวเอง
TriCore

30
@TriCore Sprting เป็นกรอบกำหนด "กฎ" สำหรับคุณคืองานของตน :)
Walfrat

คำตอบ:


1500

จากSpring Documentation :

@Repositoryคำอธิบายประกอบเป็นเครื่องหมายสำหรับการเรียนใด ๆ ที่ตอบสนองบทบาทหรือตายตัวของพื้นที่เก็บข้อมูล (หรือเรียกว่าการเข้าถึงข้อมูลหรือวัตถุ DAO บริการ) ท่ามกลางการใช้เครื่องหมายนี้คือการแปลอัตโนมัติของข้อยกเว้นตามที่อธิบายในการแปลข้อยกเว้น

ฤดูใบไม้ผลิให้คำอธิบายประกอบตายตัวเพิ่มเติม: @Component, และ@Service เป็นกฎตายตัวทั่วไปสำหรับส่วนประกอบใด ๆ ที่จัดการโดยสปริง , และเป็นความเชี่ยวชาญของกรณีการใช้งานที่เฉพาะเจาะจงมากขึ้น (ในการคงอยู่, บริการและเลเยอร์การนำเสนอตามลำดับ) ดังนั้นคุณสามารถใส่คำอธิบายประกอบการเรียนส่วนประกอบของคุณด้วยแต่โดย annotating พวกเขาด้วย, หรือ แทนชั้นเรียนของคุณมีความเหมาะสมมากขึ้นอย่างถูกต้องสำหรับการประมวลผลโดยใช้เครื่องมือหรือเชื่อมโยงกับแง่มุม@Controller@Component@Repository@Service@Controller@Component@Component@Repository@Service@Controller

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

┌──────────────┬─────────────────────────────────────────────────────┐
 Annotation    Meaning                                             
├──────────────┼─────────────────────────────────────────────────────┤
  @Component   generic stereotype for any Spring-managed component 
  @Repository  stereotype for persistence layer                    
  @Service     stereotype for service layer                        
  @Controller  stereotype for presentation layer (spring-mvc)      
└──────────────┴─────────────────────────────────────────────────────┘

6
มีความเหมาะสมที่จะเพิ่ม @Controller (หรือ @Component) ลงใน @WebServlet หรือไม่ มันไม่ใช่คอนโทรลเลอร์ Spring MVC แต่นั่นเป็นแนวคิดที่ใกล้เคียงที่สุด สิ่งที่เกี่ยวกับตัวกรอง servlet?
Rick

1
"@Repository ได้รับการสนับสนุนเป็นเครื่องหมายสำหรับการแปลข้อยกเว้นอัตโนมัติในเลเยอร์การคงอยู่ของคุณ" หมายความว่าอย่างไร
แจ็ค

9
มันอ้างถึงข้อเท็จจริงที่ว่าคำอธิบายประกอบเหล่านี้เป็นเป้าหมายที่ดีสำหรับ AOP และในขณะที่คำอธิบายประกอบอื่น ๆ ยังไม่ได้กำหนดจุดตัด แต่พวกเขาอาจทำเช่นนั้นในอนาคต ในทางกลับกัน @Repository เป็นเป้าหมายของ pointcut ในปัจจุบันอยู่แล้ว Pointcut นั้นใช้สำหรับการแปลข้อยกเว้นนั่นคือการแปลข้อยกเว้นเฉพาะเทคโนโลยีให้เป็นแบบสปริงทั่วไปเพื่อหลีกเลี่ยงการแต่งงานกันอย่างแน่นหนา
stivlo

3
@stivlo: ฉันได้พยายามเข้าใจคำว่า 'ตายตัว' จริงๆแล้วยังไม่เข้าใจ คุณช่วยฉันเข้าใจคำศัพท์นี้ได้ไหม มันช่วยได้มากและขอบคุณมาก ๆ
Premraj

2
@xenoterracide นอกจากนี้ในทางปฏิบัติไม่แตกต่างกันมาก บางสิ่งบางอย่างกับข้อเขียน@Service คือยังมี@Component(เพราะ@Serviceคำอธิบายประกอบตัวเองจะถูกกำกับด้วย@Component) เท่าที่ฉันรู้ไม่มีอะไรในกรอบของ Spring ที่ใช้ประโยชน์จากความจริงที่ว่าบางสิ่งเป็นอย่างชัดเจน@Serviceดังนั้นความแตกต่างจึงเป็นเพียงแนวคิดเท่านั้น
Jesper

801

เนื่องจากคำตอบจำนวนมากระบุว่าใช้คำอธิบายประกอบเหล่านี้แล้วเราจะเน้นที่ความแตกต่างเล็กน้อยระหว่างคำเหล่านี้

ก่อนอื่นความคล้ายคลึงกัน

จุดแรกที่ควรเน้นอีกครั้งคือการสแกนด้วยการตรวจจับอัตโนมัติและการฉีดพึ่งพาสำหรับ BeanDefinitionคำอธิบายประกอบเหล่านี้ทั้งหมด (viz., @Component, @Service, @Repository, @Controller) เหมือนกัน เราสามารถใช้งานแทนกันได้และยังสามารถไปต่อได้


ความแตกต่างระหว่าง @Component, @Repository, @Controller และ @Service

@Component

นี่คือคำอธิบายประกอบแบบแผนตายตัวทั่วไปที่บ่งบอกว่าคลาสเป็นส่วนประกอบสปริง

มีอะไรพิเศษเกี่ยวกับ @Component
<context:component-scan>เพียงสแกน@Componentและไม่ได้มองหา@Controller,@Serviceและ@Repositoryโดยทั่วไป @Componentพวกเขาจะถูกสแกนเพราะพวกเขาเองจะกำกับด้วย

เพียงแค่ใช้เวลาดูที่@Controller, @Serviceและ@Repositoryคำจำกัดความของคำอธิบายประกอบ:

@Component
public @interface Service {
    ….
}

 

@Component
public @interface Repository {
    ….
}

 

@Component
public @interface Controller {
    
}

ดังนั้นก็ไม่ผิดที่จะกล่าวว่า@Controller, @Serviceและ@Repositoryประเภทพิเศษของ@Componentคำอธิบายประกอบ <context:component-scan>เลือกพวกเขาและลงทะเบียนคลาสต่อไปนี้เป็น beans เช่นเดียวกับที่ใส่หมายเหตุประกอบ@Componentไว้

คำอธิบายประกอบแบบพิเศษจะถูกสแกนด้วยเช่นกันเนื่องจากมีการเพิ่มความคิดเห็นด้วย@Componentหมายเหตุประกอบ@Componentเอง หากเรากำหนดคำอธิบายประกอบที่กำหนดเองของเราเองและใส่คำอธิบายประกอบด้วย@Componentก็จะถูกสแกนด้วย<context:component-scan>


@Repository

นี่คือเพื่อระบุว่าคลาสกำหนดที่เก็บข้อมูล

มีอะไรพิเศษเกี่ยวกับ @Repository

นอกจากนี้จะชี้ให้เห็นว่านี่เป็นคำอธิบายตามการกำหนดค่า , @Repositoryของงานคือการจับข้อยกเว้นแพลตฟอร์มที่เฉพาะเจาะจงและอีกครั้งโยนพวกเขาเป็นหนึ่งในฤดูใบไม้ผลิแบบครบวงจรยกเว้นไม่ถูกตรวจสอบ สำหรับสิ่งนี้เราได้รับพร้อมกับPersistenceExceptionTranslationPostProcessorว่าเราจะต้องเพิ่มในบริบทแอปพลิเคชันของ Spring ดังนี้:

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

ตัวประมวลผล bean โพสต์นี้เพิ่มที่ปรึกษาให้กับ bean ใด ๆ ที่มีหมายเหตุประกอบ@Repositoryเพื่อให้มีข้อยกเว้นเฉพาะแพลตฟอร์มใด ๆ ถูกดักจับแล้วโยนใหม่เป็นข้อยกเว้นการเข้าถึงข้อมูลที่ไม่ได้ตรวจสอบของ Spring อย่างใดอย่างหนึ่ง


@Controller

@Controllerคำอธิบายประกอบแสดงให้เห็นว่าระดับโดยเฉพาะอย่างยิ่งทำหน้าที่บทบาทของตัวควบคุมที่ @Controllerคำอธิบายประกอบทำหน้าที่เป็นกฎตายตัวสำหรับการเรียนข้อเขียนที่แสดงให้เห็นบทบาทของตัวเอง

มีอะไรพิเศษเกี่ยวกับ @Controller?

เราไม่สามารถสลับคำอธิบายประกอบนี้ด้วยสิ่งอื่นใดเช่น@Serviceหรือ@Repositoryแม้ว่าพวกเขาจะดูเหมือนกัน โปรแกรมเลือกจ่ายงานจะสแกนคลาสที่มีหมายเหตุประกอบด้วย@Controllerและตรวจจับเมธอดหมายเหตุประกอบกับ@RequestMappingหมายเหตุประกอบภายใน เราสามารถใช้@RequestMappingเปิด / ในวิธีการเหล่านั้นเท่านั้นที่มีชั้นเรียนจะมีข้อเขียน@Controllerและมันจะไม่ทำงานร่วมกับ@Component, @Service, @Repositoryฯลฯ ...

หมายเหตุ: ถ้าชั้นมีการลงทะเบียนแล้วเป็นถั่วผ่านวิธีการอื่นใด ๆ เช่นผ่าน@Beanหรือผ่าน@Component, @Serviceฯลฯ ... คำอธิบายประกอบแล้ว@RequestMappingสามารถเลือกถ้าชั้นจะยังมีคำอธิบายประกอบกับ@RequestMappingคำอธิบายประกอบ แต่นั่นเป็นสถานการณ์ที่แตกต่าง


@บริการ

@Service beans เก็บตรรกะทางธุรกิจและวิธีการโทรในเลเยอร์ที่เก็บ

มีอะไรพิเศษเกี่ยวกับ @Service?

นอกเหนือจากความจริงที่ว่ามันใช้เพื่อระบุว่ามันถือตรรกะทางธุรกิจไม่มีอะไรที่เห็นได้ชัดเจนในบันทึกย่อนี้ แต่ใครจะรู้สปริงอาจเพิ่มสิ่งพิเศษเพิ่มเติมในอนาคต


มีอะไรอีกบ้าง?

คล้ายกับข้างต้นในอนาคตฤดูใบไม้ผลิอาจเพิ่มฟังก์ชันพิเศษ@Service, @Controllerและ@Repositoryอยู่บนพื้นฐานของการประชุม layering ของพวกเขา ดังนั้นจึงเป็นความคิดที่ดีที่จะเคารพการประชุมและใช้มันให้สอดคล้องกับเลเยอร์


'PersistenceExceptionTranslationPostProcessor' จะถูกลงทะเบียนโดยอัตโนมัติหากตรวจพบ JPA
Olga

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

แล้วคำอธิบายประกอบ @Service หมายถึงอะไรสำหรับ Hibernate (Persistence Layer) นอกเหนือจากคุณสมบัติ DI แล้วสิ่งที่เกี่ยวกับ Persistence Layer Proxy สำหรับการดึงและการแมปประเภทของเอนทิตีกับ DTO ที่เกี่ยวข้อง? เลเยอร์นี้มีความสำคัญอย่างยิ่งสำหรับพลวัตในเลเยอร์คงอยู่ ถ้าใครรู้ลึกว่ามันส่งผลกระทบต่อ JPA มันจะมีประโยชน์มากมาก)))
Musa

1
มีข้อมูลที่ผิดเล็กน้อยเกี่ยวกับการ@Controllerเพิ่มความคิดเห็น ไม่จำเป็นหากคลาสถูกใส่คำอธิบายประกอบด้วย@RequestMappingและ bean ของคลาสนี้ถูกสร้างขึ้นไม่ว่าด้วยวิธีใด ถั่วใด ๆ ที่มีคำอธิบายประกอบด้วย@Controller หรือ @RequestMappingจะเข้าร่วมในการแมปคำขอของ Spring MVC สิ่งนี้มีประโยชน์สำหรับการสร้างตัวควบคุมโดยทางโปรแกรม (เช่นการใช้@Beanวิธีการ) และในเวลาเดียวกันเพื่อป้องกัน Spring พยายามสร้างมันขึ้นมาด้วยการสแกนแพ็คเกจ (ถ้าไม่สามารถแยกแพ็คเกจออกจากการสแกนได้)
Ruslan Stelmachenko

1
นี่ควรเป็นคำตอบที่ได้รับการโหวตสูงสุด - ตอบคำถามทุกข้อและลงลึกมาก @stivlo ไม่ได้อธิบายเกี่ยวกับคำถาม OP แรก - ความแตกต่างทางเทคนิค
kiedysktos

430

พวกเขาเกือบจะเหมือนกัน - ทั้งหมดหมายความว่าคลาสนั้นเป็น Spring bean @Service, @Repositoryและ@Controllerมีความเชี่ยวชาญ@Components คุณสามารถเลือกที่จะดำเนินการเฉพาะกับพวกเขา ตัวอย่างเช่น:

  • @Controller ถั่วจะถูกใช้โดย spring-mvc
  • @Repository beans มีสิทธิ์ได้รับการแปลข้อยกเว้นการคงอยู่

อีกสิ่งหนึ่งคือคุณกำหนดส่วนประกอบทางความหมายไปยังเลเยอร์ต่างๆ

สิ่งหนึ่งที่@Componentเสนอคือการที่คุณสามารถใส่คำอธิบายประกอบคำอธิบายประกอบอื่น ๆ @Serviceกับมันแล้วใช้พวกเขาแบบเดียวกับที่

เช่นฉันเพิ่งทำ:

@Component
@Scope("prototype")
public @interface ScheduledJob {..}

ดังนั้นคลาสทั้งหมดที่มีหมายเหตุประกอบด้วย@ScheduledJobคือถั่วฤดูใบไม้ผลิและนอกจากนั้นจะถูกลงทะเบียนเป็นงานควอตซ์ คุณเพียงแค่ต้องให้รหัสที่จัดการบันทึกย่อที่เฉพาะเจาะจง


1
@Component หมายถึง spring bean เท่านั้นมีจุดประสงค์อื่นอีกหรือไม่
kapil das

21
@Component beans ตรวจจับอัตโนมัติโดยสปริงคอนเทนเนอร์ คุณไม่จำเป็นต้องกำหนด bean ในไฟล์กำหนดค่าระบบจะตรวจพบอัตโนมัติเมื่อรันไทม์โดย Spring
Akash5288

1
ฉันค่อนข้างชอบ @Component ทั่วไปโดยเฉพาะอย่างยิ่งในคอมโบกับ @Scope (proxyMode = ScopedProxyMode.//MODE)
Eddie B

365

@Component เทียบเท่า

<bean>

@Service, @Controller, @Repository = {@Component + ฟังก์ชั่นพิเศษเพิ่มเติม}

นั่นหมายถึงการบริการผู้ควบคุมและพื้นที่เก็บข้อมูลนั้นใช้งานได้เหมือนกัน

คำอธิบายประกอบทั้งสามนี้ใช้เพื่อแยก"เลเยอร์"ในแอปพลิเคชันของคุณ

  • ผู้ควบคุมเพียงแค่ทำสิ่งต่าง ๆ เช่นการส่งต่อการส่งต่อการเรียกวิธีการบริการ ฯลฯ
  • การบริการเพื่อธุรกิจตรรกะการคำนวณและอื่น ๆ
  • พื้นที่เก็บข้อมูลเป็น DAOs (Data Access Objects) ซึ่งเข้าถึงฐานข้อมูลโดยตรง

ตอนนี้คุณอาจถามว่าทำไมแยกพวกมันออก: (ฉันถือว่าคุณรู้จักโปรแกรม AOP-Aspect Oriented)

สมมติว่าคุณต้องการตรวจสอบกิจกรรมของ DAO Layer เท่านั้น คุณจะเขียนคลาส Aspect (A class) ที่มีการบันทึกก่อนและหลังการเรียกใช้ DAO ทุกวิธีคุณสามารถทำได้โดยใช้ AOP เนื่องจากคุณมีเลเยอร์ที่แตกต่างกันสามชั้นและไม่ผสมกัน

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

ลองนึกภาพถ้ามีเพียงคำอธิบายประกอบ @Controller แล้วส่วนนี้จะมีการจัดส่งตรรกะทางธุรกิจและการเข้าถึงฐานข้อมูลทั้งหมดผสมรหัสสกปรกมาก!

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


6
ฉันได้รับคำถามพื้นฐาน - มีคำอธิบายประกอบที่ใช้โดยกลไกสปริงหรือเป็นเพียงเพื่อให้โปรแกรมเมอร์จำสิ่งที่ชิ้นส่วนของรหัสทำ
user107986

25
@ user107986 พวกเขาส่วนใหญ่จะให้โปรแกรมเมอร์จดจำเลเยอร์ในแอปพลิเคชัน อย่างไรก็ตาม@Respositoryยังมีคุณสมบัติการแปลข้อยกเว้นอัตโนมัติ เช่นเดียวกับเมื่อมีข้อยกเว้นเกิดขึ้นใน@Repositoryตัวจัดการมักจะมีตัวจัดการสำหรับข้อยกเว้นนั้นและไม่จำเป็นต้องเพิ่มลอง catch catch blocks ในคลาส DAO มันถูกใช้พร้อมกับ PersistenceExceptionTranslationPostProcessor
โอลิเวอร์

คุณช่วยเขียนโค้ดตัวอย่างวิธีเขียนคะแนนร่วมสำหรับคลาส "@ Repository" ทั้งหมดได้ไหม ไม่ว่าเราจะใช้นิพจน์หรือใช้ชื่อ bean แต่วิธีที่เราสามารถพูดคำแนะนำนี้จะใช้กับคลาส "@ Repository" ทั้งหมดฉันพยายามรับตัวอย่างของสิ่งนี้ แต่ไม่สามารถหาได้
Moni

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

224

ในฤดูใบไม้ผลิ@Component, @Service, @Controllerและ@Repositoryจะมีคำอธิบายประกอบมโนทัศน์ที่ใช้สำหรับ:

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

@Service: ตรรกะทางธุรกิจทั้งหมดอยู่ที่นี่เช่นการคำนวณที่เกี่ยวข้องกับข้อมูลและคำอธิบายประกอบทั้งหมดของเลเยอร์ธุรกิจซึ่งผู้ใช้ของเราไม่ได้เรียกวิธีการคงอยู่โดยตรงดังนั้นมันจะเรียกวิธีนี้โดยใช้คำอธิบายประกอบนี้ มันจะร้องขอ @Repository ตามคำขอของผู้ใช้

@Repository: นี่คือ Persistence layer (Data Access Layer) ของแอปพลิเคชั่นที่ใช้รับข้อมูลจากฐานข้อมูล เช่นการดำเนินการทั้งหมดที่เกี่ยวข้องกับฐานข้อมูลจะทำโดยพื้นที่เก็บข้อมูล

@Component - ใส่คำอธิบายประกอบส่วนประกอบอื่น ๆ ของคุณ (เช่นคลาสทรัพยากร REST) ​​ด้วย stereotype ของส่วนประกอบ

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

คำอธิบายประกอบในระดับชั้นอื่น ๆ อาจพิจารณาว่าเป็นการระบุองค์ประกอบเช่นกันโดยทั่วไปเป็นองค์ประกอบพิเศษชนิด: เช่นคำอธิบายประกอบ @Repository หรือคำอธิบายประกอบ @Aspect ของ AspectJ

ป้อนคำอธิบายรูปภาพที่นี่


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

2
ตรรกะทางธุรกิจทั้งหมดไม่ควรเข้าใช้บริการ! บริการในแง่ของ DDD ควรมีตรรกะโดเมนที่มีผลกระทบมากกว่าหนึ่งเอนทิตี ดูคำตอบstackoverflow.com/a/41358034/238134
deamon

@deamon ใช่ แต่มันขึ้นอยู่กับวิธีการของนักพัฒนา
Harshal Patil

4
@HarshalPatil แน่นอนคุณสามารถเขียนแอปพลิเคชันด้วยตรรกะทางธุรกิจทั้งหมดในการให้บริการ แต่นั่นจะนำไปสู่รูปแบบโดเมน anemic และมันจะทำให้ไม่จำเป็นอย่างหนักในการบังคับใช้ข้อ จำกัด และความสอดคล้องกับเอนทิตี
deamon

1
แน่นอนมันขึ้นอยู่กับวิธีการของนักพัฒนา ทุกอย่างทำ หากคุณเข้าถึงปัญหาอย่างไม่ถูกต้องเช่นเขียนสิ่งที่คุณต้องการโดยไม่มีโครงสร้างและบอกว่ามันเป็น "แนวทางของคุณ" - มันไม่ได้ทำให้ถูกต้อง แน่นอนว่า "ถูกต้อง" และ "ผิด" ถูกใช้เป็นคำศัพท์เพื่ออธิบายแนวทางการพัฒนาซอฟต์แวร์ที่ดีเช่น SOLID และหลักการอื่น ๆ เมื่อเทียบกับแนวทางปฏิบัติซอฟต์แวร์ที่ไม่ดีเช่น "ฉันแค่ต้องการให้เป็นแบบนี้มาก่อน" และคล้ายกัน
milosmns

71

Spring 2.5 แนะนำคำอธิบายประกอบแบบตายตัวเพิ่มเติม: @Component, @Service และ @Controller @Component ทำหน้าที่เป็นแบบแผนทั่วไปสำหรับองค์ประกอบใด ๆ ที่จัดการโดยสปริง ในขณะที่ @Repository, @Service และ @Controller ทำหน้าที่เป็นความเชี่ยวชาญของ @Component สำหรับกรณีการใช้งานที่เฉพาะเจาะจงมากขึ้น (เช่นในการคงอยู่บริการและเลเยอร์การนำเสนอตามลำดับ) สิ่งนี้หมายความว่าคุณสามารถใส่คำอธิบายประกอบคลาสคอมโพเนนต์ด้วย @Component แต่โดยการเพิ่มความคิดเห็นด้วย @Repository, @Service หรือ @Controller แทนคลาสของคุณจะเหมาะสำหรับการประมวลผลโดยใช้เครื่องมือหรือเชื่อมโยงกับแง่มุมต่างๆ ตัวอย่างเช่นคำอธิบายประกอบแบบตายตัวเหล่านี้สร้างเป้าหมายในอุดมคติสำหรับจุดทางลัด แน่นอนว่ายังเป็นไปได้ว่า @Repository, @Service และ @Controller อาจมีความหมายเพิ่มเติมในการเผยแพร่ Spring Framework ในอนาคต ดังนั้น, หากคุณตัดสินใจใช้ @Component หรือ @Service สำหรับเลเยอร์บริการของคุณ @Service เป็นตัวเลือกที่ดีกว่าอย่างชัดเจน ตามที่ระบุข้างต้น @Repository ได้รับการสนับสนุนเป็นเครื่องหมายสำหรับการแปลข้อยกเว้นอัตโนมัติในเลเยอร์การคงอยู่ของคุณ

@Component  Indicates a auto scan component.
@Repository  Indicates DAO component in the persistence layer.
@Service  Indicates a Service component in the business layer.
@Controller  Indicates a controller component in the presentation layer.

การอ้างอิง: - Spring Documentation - การสแกนคลาสพา ธ , คอมโพเนนต์ที่ได้รับการจัดการและการกำหนดค่าการเขียนโดยใช้ Java


48

เทคนิค@Controller, @Service, @Repositoryเหมือนกันทั้งหมด @Componentทั้งหมดของพวกเขาขยาย

จากซอร์สโค้ด Spring:

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

เราโดยตรงสามารถใช้@Componentสำหรับแต่ละและถั่ว แต่เพื่อความเข้าใจที่ดีขึ้นและการบำรุงรักษาของแอพลิเคชันที่มีขนาดใหญ่เราจะใช้@Controller, ,@Service@Repository

วัตถุประสงค์ของการเพิ่มความคิดเห็นแต่ละรายการ:

  1. @Controller-> คลาสที่มีคำอธิบายประกอบนี้มีวัตถุประสงค์เพื่อรับคำขอจากฝั่งไคลเอ็นต์ คำขอแรกมาถึง Dispatcher Servlet จากที่ผ่านการร้องขอไปยังตัวควบคุมเฉพาะโดยใช้ค่าของ@RequestMappingคำอธิบายประกอบ
  2. @Service-> คลาสที่มีคำอธิบายประกอบนี้มีวัตถุประสงค์เพื่อจัดการข้อมูลที่เราได้รับจากลูกค้าหรือดึงข้อมูลจากฐานข้อมูล การจัดการกับข้อมูลทั้งหมดควรทำในเลเยอร์นี้
  3. @Repository-> คลาสที่มีคำอธิบายประกอบนี้มีวัตถุประสงค์เพื่อเชื่อมต่อกับฐานข้อมูล นอกจากนี้ยังสามารถพิจารณาเป็นเลเยอร์ DAO (Data Access Object) เลเยอร์นี้ควรถูก จำกัด ให้ดำเนินการ CRUD (สร้างดึงอัปเดตลบ) เท่านั้น หากการจัดการใด ๆ ที่จำเป็นข้อมูลควรจะถูกส่งไปส่งกลับไปที่ชั้น @Service

หากเราแลกเปลี่ยนตำแหน่ง (ใช้@Repositoryแทน@Controller) แอปพลิเคชันของเราจะทำงานได้ดี

วัตถุประสงค์หลักของการใช้สามแบบที่แตกต่างกัน@annotationsคือเพื่อให้ Modularity ที่ดีขึ้นสำหรับแอปพลิเคชัน Enterprise


2
คุณหมายถึงอะไรโดยการแทนที่สถานที่แลกเปลี่ยน controller and repository
Ashish Kamble

46

การใช้@Serviceและ@Repositoryหมายเหตุประกอบมีความสำคัญจากมุมมองการเชื่อมต่อฐานข้อมูล

  1. ใช้@Serviceสำหรับการเชื่อมต่อฐานข้อมูลประเภทบริการเว็บทั้งหมดของคุณ
  2. ใช้@Repositoryสำหรับการเชื่อมต่อฐานข้อมูล proc ที่เก็บไว้ทั้งหมดของคุณ

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


@Repository สามารถใช้สำหรับการโทรของ RestAPI แทนการทำงานของฐานข้อมูลได้หรือไม่?
Nayeem

@Nayeem ในทางเทคนิคคุณสามารถใส่คำอธิบายประกอบการบริการเป็นตัวควบคุมและที่เก็บข้อมูลเป็นบริการการฉีดพึ่งพาจะทำงานได้เหมือนกัน แต่ทำไมคุณจะทำเช่นนั้น? ถ้ามันไม่ทำงานกับเอนทิตีฐานข้อมูล - มันไม่ใช่ที่เก็บและ@Repositoryถูกออกแบบมาโดยเฉพาะเพื่อทำงานกับเลเยอร์การคงอยู่ หากคุณกำลังทำงานกับส่วนที่เหลือ api - คุณกำลังทำงานกับ DTO ไม่ใช่ DAO
เบ็น

28

@Repository @Serviceและ@Controllerทำหน้าที่เป็นผู้เชี่ยวชาญของ @Component สำหรับการใช้งานที่เฉพาะเจาะจงมากขึ้นบนพื้นฐานนั้นคุณสามารถแทนที่ @Service เป็น @Component แต่ในกรณีนี้คุณจะสูญเสียความเชี่ยวชาญ

1. **@Repository**   - Automatic exception translation in your persistence layer.
2. **@Service**      - It indicates that the annotated class is providing a business service to other layers within the application.

27

คำอธิบายประกอบทั้งหมดเหล่านี้เป็นประเภทของประเภทคำอธิบายประกอบแบบสเตอริโอความแตกต่างระหว่างคำอธิบายประกอบทั้งสามนี้คือ

  • ถ้าเราเพิ่ม @Component แล้วมันจะบอกว่าบทบาทของ class เป็น class component หมายความว่ามันเป็นคลาสที่ประกอบไปด้วยตรรกะบางอย่าง แต่มันไม่ได้บอกว่า class ที่มีธุรกิจเฉพาะหรือตรรกะการคงอยู่หรือคอนโทรลเลอร์ดังนั้นเราจึงไม่ใช้ โดยตรงคำอธิบายประกอบ @Component นี้
  • หากเราเพิ่มคำอธิบายประกอบ @Service มันจะบอกว่าบทบาทของคลาสประกอบด้วยตรรกะทางธุรกิจ
  • ถ้าเราเพิ่ม @Repository ไว้ด้านบนของคลาสมันจะบอกว่าคลาสนั้นประกอบด้วยตรรกะการคงอยู่
  • Here @Component เป็นคำอธิบายประกอบพื้นฐานสำหรับคำอธิบายประกอบ @ Service, @ Repository และ @Controller

ตัวอย่างเช่น

package com.spring.anno;
@Service
public class TestBean
{
    public void m1()
    {
       //business code
    }
}

package com.spring.anno;
@Repository
public class TestBean
{
    public void update()
    {
       //persistence code
    }
}
  • เมื่อใดก็ตามที่เราเพิ่ม@Serviceหรือ@Repositroyหรือ@Controllerคำอธิบายประกอบโดยค่าเริ่มต้น@Componentคำอธิบายประกอบเป็นไปเพื่อการดำรงอยู่ด้านบนของชั้นเรียน

23

ฤดูใบไม้ผลิให้สี่ประเภทที่แตกต่างกันของส่วนประกอบรถยนต์คำอธิบายประกอบสแกนพวกเขามี@Component, @Service, และ@Repository @Controllerในทางเทคนิคแล้วไม่มีความแตกต่างระหว่างสิ่งเหล่านั้น แต่ควรใช้คำอธิบายประกอบการสแกนส่วนประกอบอัตโนมัติเพื่อวัตถุประสงค์พิเศษและภายในเลเยอร์ที่กำหนด

@Component: เป็นคำอธิบายประกอบในการสแกนส่วนประกอบอัตโนมัติพื้นฐานมันระบุคลาสที่มีคำอธิบายประกอบเป็นองค์ประกอบสแกนอัตโนมัติ

@Controller: คลาสที่มีคำอธิบายประกอบเป็นการระบุว่ามันเป็นส่วนประกอบของตัวควบคุมและส่วนใหญ่จะใช้ในชั้นนำเสนอ

@Service: มันหมายถึงคลาสที่มีคำอธิบายประกอบเป็นองค์ประกอบบริการในชั้นธุรกิจ

@Repository: คุณต้องใช้คำอธิบายประกอบนี้ภายในเลเยอร์การคงอยู่สิ่งนี้ทำหน้าที่เหมือนกับที่เก็บฐานข้อมูล

เราควรเลือกรูปแบบที่พิเศษกว่า@Componentขณะที่ใส่คำอธิบายประกอบในชั้นเรียนเนื่องจากคำอธิบายประกอบนี้อาจมีพฤติกรรมที่เฉพาะเจาะจงในอนาคต


20

เราสามารถตอบได้ตามมาตรฐานจาวา

การอ้างอิงJSR-330ซึ่งตอนนี้ได้รับการสนับสนุนโดยสปริงคุณสามารถใช้@Namedเพื่อกำหนดถั่ว (อย่างใด@Named=@Component) ดังนั้นตามมาตรฐานนี้ดูเหมือนว่าจะมีการใช้งานในการกำหนดแบบแผน (ที่ไม่เหมือนใคร@Repository, @Service, @Controller) ถั่วประเภท

แต่ผู้ใช้สปริงจะมีคำอธิบายประกอบต่างกันเหล่านี้ต่างกันสำหรับการใช้งานเฉพาะตัวอย่างเช่น

  1. ช่วยให้นักพัฒนากำหนดหมวดหมู่ที่ดีขึ้นสำหรับพนักงานเจ้าหน้าที่ การจัดหมวดหมู่นี้อาจมีประโยชน์ในบางกรณี (ตัวอย่างเช่นเมื่อคุณใช้aspect-orientedสิ่งเหล่านี้อาจเป็นตัวเลือกที่ดีสำหรับpointcuts)
  2. @Repository คำอธิบายประกอบจะเพิ่มฟังก์ชันการทำงานบางอย่างให้กับ bean ของคุณ (การแปลข้อยกเว้นอัตโนมัติไปยังเลเยอร์การคงอยู่ของถั่ว)
  3. หากคุณกำลังใช้ MVC ฤดูใบไม้ผลิ@RequestMappingสามารถเพิ่มไปยังคลาสที่มีคำอธิบายประกอบ@Controllerเท่านั้น

เกี่ยวกับประเด็นที่ 3 ของคุณ ที่ไม่เป็นความจริง. ฉันสามารถเพิ่มคำอธิบายประกอบ @RequestMapping แม้กับวิธีการภายใต้ระดับบริการเช่นกัน (ฉันหมายถึงคลาสที่กำกับด้วย @Service)
ราหุลกัปต้า

19

อธิบายส่วนประกอบอื่น ๆ ด้วย @Component ตัวอย่างเช่นคลาส REST Resource

@Component
public class AdressComp{
    .......
    ...//some code here    
}

@Component เป็นกฎตายตัวทั่วไปสำหรับองค์ประกอบใด ๆ ของ Spring ที่ได้รับการจัดการ

@Controller, @Service และ @Repository เป็นความเชี่ยวชาญของ @Component สำหรับกรณีการใช้งานเฉพาะ

@ ส่วนประกอบในฤดูใบไม้ผลิ

"ความเชี่ยวชาญเฉพาะด้าน"


18

มีความแตกต่างระหว่างไม่เป็น@Component, @Service, , @Controller เป็นคำอธิบายประกอบทั่วไปเพื่อเป็นตัวแทนองค์ประกอบของ MVC ของเรา แต่จะมีส่วนประกอบหลายส่วนซึ่งเป็นส่วนหนึ่งของแอปพลิเคชัน MVC ของเราเช่นส่วนประกอบของชั้นบริการส่วนประกอบของชั้นที่มีอยู่และส่วนประกอบของชั้นนำเสนอ ดังนั้นเพื่อให้เห็นความแตกต่างพวกเขาคนในฤดูใบไม้ผลิจึงให้คำอธิบายประกอบอีกสามรายการด้วย@Repository@Component

  • เพื่อแสดงส่วนประกอบเลเยอร์คงอยู่: @Repository
  • ในการแสดงส่วนประกอบของเลเยอร์บริการ: @Service
  • ในการแสดงส่วนประกอบเลเยอร์การนำเสนอ: @Controller
  • หรืออื่น ๆ ที่คุณสามารถใช้@Componentสำหรับพวกเขาทั้งหมด

17

แม้ว่าเราจะแลกเปลี่ยน @Component หรือ @Repository หรือ @service

มันจะทำงานเหมือนเดิม แต่แง่มุมหนึ่งคือพวกเขาจะไม่สามารถรับข้อยกเว้นเฉพาะบางอย่างที่เกี่ยวข้องกับ DAO แทนที่จะเป็นที่เก็บถ้าเราใช้ component หรือ @ service


15

ใน Spring 4 เวอร์ชันล่าสุด:

คำอธิบายประกอบ @Repository เป็นเครื่องหมายสำหรับชั้นเรียนใด ๆ ที่ตอบสนองบทบาทหรือต้นแบบของพื้นที่เก็บข้อมูล (หรือที่เรียกว่า Data Access Object หรือ DAO) ในบรรดาการใช้เครื่องหมายนี้เป็นการแปลข้อยกเว้นโดยอัตโนมัติตามที่อธิบายไว้ในส่วน 20.2.2“ การแปลข้อยกเว้น”

Spring ให้คำอธิบายประกอบตายตัวเพิ่มเติม: @Component, @Service และ @Controller @Component เป็นกฎตายตัวทั่วไปสำหรับองค์ประกอบใด ๆ ที่จัดการโดยสปริง @Repository, @Service และ @Controller เป็นความเชี่ยวชาญของ @Component สำหรับกรณีการใช้งานที่เฉพาะเจาะจงมากขึ้นตัวอย่างเช่นในการคงอยู่บริการและเลเยอร์การนำเสนอตามลำดับ ดังนั้นคุณสามารถใส่คำอธิบายประกอบคลาสคอมโพเนนต์ด้วย @Component แต่โดยการเพิ่มคำอธิบายประกอบด้วย @Repository, @Service หรือ @Controller แทนคลาสของคุณจะเหมาะสมกว่าสำหรับการประมวลผลโดยใช้เครื่องมือหรือเชื่อมโยงกับแง่มุมต่างๆ ตัวอย่างเช่นคำอธิบายประกอบแบบตายตัวเหล่านี้สร้างเป้าหมายในอุดมคติสำหรับจุดทางลัด เป็นไปได้ว่า @Repository, @Service และ @Controller อาจมีความหมายเพิ่มเติมในการเผยแพร่ Spring Framework ในอนาคต ดังนั้น, หากคุณเลือกระหว่างการใช้ @Component หรือ @Service สำหรับเลเยอร์บริการของคุณ @Service เป็นตัวเลือกที่ดีกว่าอย่างชัดเจน ตามที่ระบุข้างต้น @Repository ได้รับการสนับสนุนเป็นเครื่องหมายสำหรับการแปลข้อยกเว้นอัตโนมัติในเลเยอร์การคงอยู่ของคุณ


15

@Component : คุณใส่คำอธิบายประกอบคลาส@Componentมันจะจำศีลว่าเป็น Bean

@ Repository : คุณใส่คำอธิบายประกอบคลาส@Repositoryมันจะบอกให้จำศีลว่าเป็นคลาส DAO และถือเป็นคลาส DAO หมายความว่ามันจะทำให้ข้อยกเว้นไม่ จำกัด (โยนลงมาจากวิธีการ DAO) DataAccessExceptionมีสิทธิ์ได้รับการแปลเป็นฤดูใบไม้ผลิ

@Service : นี่เป็นการบอกให้จำศีลว่าเป็นคลาส Service ที่คุณจะมี@Transactionalคำอธิบายประกอบเลเยอร์บริการ ฯลฯ เพื่อให้จำศีลในฐานะองค์ประกอบบริการ

พลัสเป็นล่วงหน้า@Service @Componentสมมติว่าชื่อคลาสของ bean คือCustomerServiceเนื่องจากคุณไม่ได้เลือกวิธีกำหนดค่า XML bean ดังนั้นคุณจึงใส่คำอธิบายประกอบ bean ด้วย@Componentเพื่อระบุว่าเป็น Bean ดังนั้นในขณะที่รับอ็อบเจกต์ bean CustomerService cust = (CustomerService)context.getBean("customerService");โดยปกติสปริงจะลดตัวอักษรตัวแรกขององค์ประกอบให้เล็กลง - จาก 'CustomerService' ถึง 'customerService' และคุณสามารถเรียกคืนคอมโพเนนต์นี้ด้วยชื่อ 'customerService' แต่ถ้าคุณใช้@Serviceคำอธิบายประกอบสำหรับคลาส bean คุณสามารถระบุชื่อ bean เฉพาะได้

@Service("AAA")
public class CustomerService{

และคุณสามารถรับวัตถุถั่วโดย

CustomerService cust = (CustomerService)context.getBean("AAA");

13

@Component เป็นคำอธิบายประกอบทั่วไปในระดับบนสุดซึ่งทำให้ถั่วที่มีคำอธิบายประกอบถูกสแกนและพร้อมใช้งานในคอนเทนเนอร์ DI

@Repository เป็นคำอธิบายประกอบแบบพิเศษและนำคุณสมบัติของการแปลงข้อยกเว้นที่ไม่ได้ตรวจสอบทั้งหมดจากคลาส DAO

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

@Controller เป็นคำอธิบายประกอบแบบพิเศษซึ่งทำให้ MVC bean ทราบและอนุญาตให้ใช้คำอธิบายประกอบเพิ่มเติมเช่น@RequestMappingและทั้งหมด

นี่คือรายละเอียดเพิ่มเติม


11

A @Serviceถึงใบเสนอราคาเอกสารฤดูใบไม้ผลิ

ระบุว่าคลาสที่ทำหมายเหตุประกอบไว้คือ "Service" ซึ่งแต่เดิมกำหนดโดย Domain-Driven Design (Evans, 2003) เป็น "การดำเนินการที่นำเสนอเป็นอินเทอร์เฟซที่ยืนอยู่คนเดียวในรูปแบบโดยไม่มีสถานะห่อหุ้ม" อาจระบุได้ว่าคลาสนั้นเป็น "Business Service Facade" (ในรูปแบบ Core J2EE) หรือสิ่งที่คล้ายกัน คำอธิบายประกอบนี้เป็นกฎตายตัวทั่วไปและแต่ละทีมอาจ จำกัด ความหมายและใช้ตามความเหมาะสม

ถ้าคุณดูการออกแบบที่ขับเคลื่อนด้วยโดเมนโดย eric evans

SERVICE คือการดำเนินการที่นำเสนอเป็นอินเทอร์เฟซที่โดดเดี่ยวในโมเดลโดยไม่ต้องมีการห่อหุ้มสถานะเช่นเดียวกับ ENTITIES และ VALUE OBJECTS บริการเป็นรูปแบบทั่วไปในกรอบทางเทคนิค แต่พวกเขายังสามารถนำไปใช้ในชั้นโดเมน บริการชื่อเน้นความสัมพันธ์กับวัตถุอื่น ๆ แตกต่างจาก ENTITIES และค่าวัตถุประสงค์มันถูกกำหนดอย่างหมดจดในแง่ของสิ่งที่มันสามารถทำได้สำหรับลูกค้า SERVICE มีแนวโน้มที่จะได้รับการตั้งชื่อให้กับกิจกรรมมากกว่าเป็นเอนทิตีคำกริยาแทนคำนาม SERVICE ยังคงมีคำจำกัดความที่เป็นนามธรรมและมีเจตนา มันมีรสชาติที่แตกต่างจากนิยามของวัตถุ SERVICE ควรยังคงมีความรับผิดชอบที่กำหนดไว้และความรับผิดชอบนั้นและอินเทอร์เฟซที่เติมเต็มควรถูกกำหนดเป็นส่วนหนึ่งของรูปแบบโดเมน ชื่อการดำเนินงานควรมาจากภาษา UBIQUITOUS หรือได้รับการแนะนำให้รู้จัก พารามิเตอร์และผลลัพธ์ควรเป็นวัตถุโดเมน ควรใช้บริการอย่างรอบคอบและไม่อนุญาตให้ตัดสิทธิ์การเข้าใช้และค่านิยมของพฤติกรรมทั้งหมดของพวกเขา แต่เมื่อการดำเนินการเป็นแนวคิดโดเมนที่สำคัญจริง SERVICE จะกลายเป็นส่วนหนึ่งของการออกแบบ MODEL-DRIVEN ประกาศในแบบจำลองในฐานะ SERVICE แทนที่จะเป็นวัตถุปลอมที่ไม่ได้แสดงถึงสิ่งใดการดำเนินการแบบสแตนด์อโลนจะไม่ทำให้ผู้อื่นเข้าใจผิด SERVICE เป็นส่วนที่เป็นธรรมชาติของการออกแบบ MODEL-DRIVEN ประกาศในแบบจำลองในฐานะ SERVICE แทนที่จะเป็นวัตถุปลอมที่ไม่ได้แสดงถึงสิ่งใดการดำเนินการแบบสแตนด์อโลนจะไม่ทำให้ผู้อื่นเข้าใจผิด SERVICE เป็นส่วนที่เป็นธรรมชาติของการออกแบบ MODEL-DRIVEN ประกาศในแบบจำลองในฐานะ SERVICE แทนที่จะเป็นวัตถุปลอมที่ไม่ได้แสดงถึงสิ่งใดการดำเนินการแบบสแตนด์อโลนจะไม่ทำให้ผู้อื่นเข้าใจผิด

และRepositoryตามอีริคอีแวนส์

REPOSITORY หมายถึงวัตถุทั้งหมดของบางประเภทเป็นชุดแนวคิด (ปกติเลียนแบบ) มันทำหน้าที่เหมือนคอลเลกชันยกเว้นด้วยความสามารถในการสอบถามที่ซับซ้อนมากขึ้น วัตถุประเภทที่เหมาะสมจะถูกเพิ่มและลบออกและเครื่องจักรที่อยู่เบื้องหลัง REPOSITORY จะแทรกหรือลบออกจากฐานข้อมูล คำจำกัดความนี้รวบรวมชุดของความรับผิดชอบที่เหนียวแน่นเพื่อให้สามารถเข้าถึงรากเหง้าของ AGGREGATES จากวงจรชีวิตในวัยเด็กจนถึงช่วงสุดท้าย


11

คำตอบที่ดีพออยู่ที่นี่เพื่ออธิบายคำอธิบายประกอบแบบต่าง ๆ ระหว่างคอมโพเนนต์ - ที่เก็บข้อมูลบริการ ฉันต้องการแบ่งปันความแตกต่างระหว่าง@Controller & @RestController

@Controller VS RestController

@RestController:

ป้อนคำอธิบายรูปภาพที่นี่

  • คำอธิบายประกอบนี้เป็นรุ่นพิเศษ@Controllerที่เพิ่ม @Controllerและใส่@ResponseBodyคำอธิบายประกอบโดยอัตโนมัติ ดังนั้นเราไม่จำเป็นต้องเพิ่ม@ResponseBodyวิธีการทำแผนที่ของเรา นั่นหมายความว่าการ @ResponseBodyใช้งานเริ่มต้น
  • หากคุณใช้@RestControllerคุณจะไม่สามารถส่งคืนมุมมอง (โดยใช้ Viewresolverใน Spring / Spring-Boot)
  • @RestControllerยังแปลงการตอบสนองJSON/XML automaticallyเป็น@ResponseBodyทำให้วัตถุที่ส่งคืนเป็นสิ่งที่อาจอยู่ในร่างกายe.g. JSON or XML

@Controller

ป้อนคำอธิบายรูปภาพที่นี่

  • @Controllerใช้เพื่อทำเครื่องหมายคลาสเป็น Spring MVC Controller คำอธิบายประกอบนี้เป็นเพียงรุ่นพิเศษ@Componentและอนุญาตให้คลาสตัวควบคุมตรวจพบอัตโนมัติตามการสแกนคลาสพา ธ
  • @Controller คุณสามารถส่งคืนมุมมองใน Spring web MVC

ดูรายละเอียดเพิ่มเติม


9

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


6

คำอธิบายของแบบแผน:

  • @Service- ใส่คำอธิบายประกอบคลาสบริการทั้งหมดของคุณด้วย @Service เลเยอร์นี้รู้ถึงหน่วยงาน ตรรกะทางธุรกิจทั้งหมดของคุณจะอยู่ในคลาสบริการ โดยทั่วไปวิธีการบริการชั้นจะครอบคลุมภายใต้การทำธุรกรรม คุณสามารถโทร DAO หลายสายได้จากวิธีการบริการหากธุรกรรมหนึ่งล้มเหลวธุรกรรมทั้งหมดควรย้อนกลับ
  • @Repository- ใส่คำอธิบายประกอบคลาส DAO ทั้งหมดของคุณด้วย @Repository ตรรกะการเข้าถึงฐานข้อมูลทั้งหมดของคุณควรอยู่ในคลาส DAO
  • @Component - ใส่คำอธิบายประกอบส่วนประกอบอื่น ๆ ของคุณ (เช่นคลาสทรัพยากร REST) ​​ด้วย stereotype ของส่วนประกอบ
  • @Autowired - ให้ Spring เชื่อมโยงถั่วอัตโนมัติเข้ากับคลาสของคุณโดยใช้คำอธิบายประกอบ @Autowired

@Componentเป็นกฎตายตัวทั่วไปสำหรับส่วนประกอบใด ๆ ที่จัดการโดยสปริง @Repository, @Serviceและ@Controllerเป็นความเชี่ยวชาญเฉพาะของ@Componentกรณีการใช้งานที่เฉพาะเจาะจงมากขึ้นตัวอย่างเช่นในการคงอยู่, บริการและเลเยอร์การนำเสนอ

แต่เดิมตอบที่นี่


5

ความแตกต่างระหว่างคำอธิบายประกอบ @Component, @Reproller, @Controller & @Service

@Component - ทั่วไปและสามารถใช้ได้ทั่วทั้งแอปพลิเคชัน
@Service - หมายเหตุประกอบคลาสที่ระดับเลเยอร์บริการ
@Controller - คำอธิบายประกอบคลาสที่ระดับเลเยอร์การนำเสนอส่วนใหญ่ใช้ใน Spring MVC
@Repository - คำอธิบายประกอบชั้นเรียนที่ชั้นความเพียรซึ่งจะทำหน้าที่เป็นที่เก็บฐานข้อมูล

@Controller= @Component (คำอธิบายประกอบภายใน) + คุณลักษณะเลเยอร์การนำเสนอ
@Service= @Component (คำอธิบายประกอบภายใน) + คุณสมบัติของเลเยอร์บริการ
@Component= ส่วนประกอบที่เกิดขึ้นจริง (ถั่ว)
@Repository= @ ส่วนประกอบ (คำอธิบายภายใน) + คุณสมบัติเลเยอร์ข้อมูล (ใช้สำหรับจัดการโดเมนถั่ว)


3

ในเฟรมเวิร์กสปริงจะมีคำอธิบายประกอบแบบพิเศษบางอย่างที่เรียกว่าคำอธิบายประกอบแบบตายตัว เหล่านี้คือ: -

@RestController- Declare at controller level.
@Controller  Declare at controller level.
@Component  Declare at Bean/entity level.
@Repository  Declare at DAO level.
@Service  Declare at BO level.

คำอธิบายประกอบที่ประกาศไว้ข้างต้นเป็นสิ่งพิเศษเพราะเมื่อเราเพิ่ม<context:component-scan>ลงในไฟล์ xxx-servlet.xml สปริงจะสร้างวัตถุของคลาสเหล่านั้นโดยอัตโนมัติซึ่งมีคำอธิบายประกอบพร้อมคำอธิบายประกอบด้านบนในระหว่างขั้นตอนการสร้าง / โหลดบริบท


2

@Component, @ Repository, @ Service, @Controller:

@Componentเป็นกฎตายตัวทั่วไปสำหรับส่วนประกอบที่มีการจัดการโดยฤดูใบไม้ผลิ@Repository, @Serviceและ@Controllerมี@Componentความเชี่ยวชาญมากขึ้นสำหรับการใช้งานที่เฉพาะเจาะจง:

  • @Repository สำหรับความเพียร
  • @Service สำหรับบริการและธุรกรรม
  • @Controller สำหรับตัวควบคุม MVC

ทำไมต้องใช้@Repository, @Service, @Controllerมากกว่า@Component? เราสามารถทำเครื่องหมายคลาสองค์ประกอบของเราด้วย @Component แต่ถ้าเราใช้ทางเลือกที่ปรับให้เข้ากับการทำงานที่คาดหวังไว้แทน ชั้นเรียนของเราเหมาะสมกับการใช้งานที่คาดหวังในแต่ละกรณี

คลาสที่มีหมายเหตุประกอบด้วย@Repositoryมีการแปลที่ดีขึ้นและการจัดการข้อผิดพลาดที่อ่านได้ด้วย org.springframework.dao.DataAccessException เหมาะอย่างยิ่งสำหรับการใช้งานส่วนประกอบที่เข้าถึงข้อมูล (DataAccessObject หรือ DAO)

คลาสที่มีคำอธิบายประกอบที่มี@Controllerบทบาทควบคุมในแอปพลิเคชัน Spring Web MVC

คลาสที่มีคำอธิบายประกอบโดย@Serviceมีบทบาทในบริการตรรกะทางธุรกิจเช่นรูปแบบ Facade สำหรับ DAO Manager (Facade) และการจัดการธุรกรรม


2

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

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

การเขียนโปรแกรมสมัยใหม่คือการประดิษฐ์ศิลปะเทคนิคและการสื่อสารในสัดส่วนที่แตกต่างกัน บิตการสื่อสารมักมีความสำคัญมากเนื่องจากโดยปกติแล้วโค้ดจะอ่านบ่อยกว่าที่เขียน ในฐานะโปรแกรมเมอร์คุณไม่เพียง แต่พยายามแก้ปัญหาทางเทคนิคเท่านั้น แต่ยังพยายามสื่อสารถึงความตั้งใจของคุณกับโปรแกรมเมอร์ในอนาคตที่อ่านรหัสของคุณ โปรแกรมเมอร์เหล่านี้อาจไม่แชร์ภาษาของคุณหรือสภาพแวดล้อมทางสังคมของคุณและเป็นไปได้ว่าพวกเขาอาจอ่านโค้ดของคุณในอีก 50 ปีข้างหน้าในอนาคต (ไม่น่าเป็นไปได้อย่างที่คุณคิด) มันยากที่จะสื่อสารอย่างมีประสิทธิภาพจนในอนาคต ดังนั้นจึงเป็นเรื่องสำคัญที่เราจะต้องใช้ภาษาที่ชัดเจนมีประสิทธิภาพมากที่สุดถูกต้องและมีการสื่อสาร

ยกตัวอย่างเช่นมันเป็นสิ่งสำคัญที่จะใช้เมื่อเรากำลังเขียนพื้นที่เก็บข้อมูลมากกว่า@Repository @Componentหลังเป็นตัวเลือกคำอธิบายประกอบที่แย่มากสำหรับที่เก็บเนื่องจากไม่ได้ระบุว่าเรากำลังดูที่เก็บข้อมูล เราสามารถสันนิษฐานได้ว่าที่เก็บเป็นสปริง - ถั่วด้วย แต่ไม่ใช่ว่าที่เก็บเป็นส่วนประกอบ เมื่อ@Repositoryเรามีความชัดเจนและเฉพาะเจาะจงในภาษาของเรา เรากำลังระบุอย่างชัดเจนว่านี่คือที่เก็บ กับ@Componentเรากำลังปล่อยให้ผู้อ่านทำการตัดสินใจว่าจะอ่านส่วนประกอบชนิดใดและพวกเขาจะต้องอ่านทั้งคลาส (และอาจเป็นต้นไม้ของคลาสย่อยและอินเทอร์เฟซ) เพื่ออนุมานความหมาย ในชั้นเรียนอาจถูกตีความผิดโดยผู้อ่านในอนาคตอันห่างไกลที่ไม่ได้เป็นที่เก็บและเราจะต้องรับผิดชอบบางส่วนสำหรับความผิดพลาดนี้เพราะเราซึ่งรู้ดีว่านี่คือที่เก็บซึ่งไม่ได้เจาะจงในภาษาของเรา และสื่อสารอย่างมีประสิทธิภาพตามเจตนาของเรา

ฉันจะไม่เข้าไปในตัวอย่างอื่น ๆ แต่จะระบุอย่างชัดเจนที่สุดเท่าที่จะทำได้: คำอธิบายประกอบเหล่านี้เป็นสิ่งที่แตกต่างอย่างสิ้นเชิงและควรใช้อย่างเหมาะสมตามความตั้งใจของพวกเขา @Repositoryใช้สำหรับที่เก็บข้อมูลและไม่มีหมายเหตุประกอบอื่นที่ถูกต้อง @Serviceใช้สำหรับบริการและไม่มีการเพิ่มความคิดเห็นอื่นใดถูกต้อง @Componentสำหรับส่วนประกอบที่ไม่ใช่ repostories หรือบริการและการใช้สิ่งใดสิ่งหนึ่งในที่นี้ก็จะไม่ถูกต้องเช่นกัน มันอาจจะรวบรวมมันอาจจะวิ่งและผ่านการทดสอบของคุณ แต่มันจะผิดและฉันจะคิดถึงคุณน้อยลง (มืออาชีพ) ถ้าคุณทำเช่นนี้

มีตัวอย่างของสิ่งนี้ตลอดฤดูใบไม้ผลิ (และการเขียนโปรแกรมโดยทั่วไป) คุณต้องไม่ใช้@Controllerเมื่อเขียน REST API เนื่องจาก@RestControllerพร้อมใช้งาน คุณต้องไม่ใช้@RequestMappingเมื่อ@GetMappingเป็นทางเลือกที่ถูกต้อง อื่น ๆ ฯลฯ คุณต้องเลือกภาษาที่ถูกต้องและแม่นยำที่สุดเท่าที่จะทำได้เพื่อสื่อสารความตั้งใจของคุณกับผู้อ่านของคุณมิฉะนั้นคุณจะแนะนำความเสี่ยงเข้าสู่ระบบของคุณและความเสี่ยงมีค่าใช้จ่าย


พูดได้ดีและเป็นจุดที่ดี!
Andy

1

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

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

@Service
public class Doer {
   // Your logic 
}

// To use it in another class, suppose in Controller 
@Controller
public class XController {
 // You have to inject it like this 
 @Autowired 
 private Doer doer;
}

ทั้งหมดเป็นวิธีเดียวกันเมื่อคุณฉีด@Repositoryเป็นส่วนต่อประสานที่ใช้การนำไปใช้กับรูปแบบการออกแบบ Repository Pattern Repositoryโดยทั่วไปจะใช้เมื่อคุณจัดการกับบางแหล่งข้อมูลหรือฐานข้อมูลและคุณจะพบว่ามีหลาย การใช้งานพร้อมให้คุณจัดการกับฐานข้อมูล มันสามารถเป็น CrudRepository , JpaRepositoryเป็นต้น

// For example
public interface DoerRepository implements JpaRepository<Long, XEntity> {}

ในที่สุด@Componentนี่เป็นรูปแบบทั่วไปสำหรับ beans ที่ลงทะเบียนใน Spring นั่นคือสปริงมักจะมองหา bean ที่ทำเครื่องหมายด้วย @Component เพื่อลงทะเบียนจากนั้นทั้ง @Service และ @Repository เป็นกรณีพิเศษของ @Component อย่างไรก็ตามกรณีการใช้งานทั่วไป สำหรับส่วนประกอบคือเมื่อคุณกำลังทำบางสิ่งบางอย่างทางเทคนิคอย่างแท้จริงไม่ใช่เพื่อครอบคลุมกรณีธุรกิจโดยตรง! เช่นวันที่จัดรูปแบบหรือมอบหมายกลไกการทำให้เป็นอนุกรมคำขอพิเศษและอื่น ๆ


0

@Componentทำหน้าที่เป็นคำอธิบายประกอบ @Bean ในคลาสการกำหนดค่าลงทะเบียน bean ในบริบทสปริง นอกจากนี้ยังเป็นพาเรนต์สำหรับคำอธิบายประกอบ @Service, @Repository และ @Controller

@Serviceขยายคำอธิบายประกอบ @Component และมีความแตกต่างในการตั้งชื่อเท่านั้น

@Repository - ขยายคำอธิบายประกอบ @Component และแปลข้อยกเว้นฐานข้อมูลทั้งหมดลงใน DataAccessException

@Controller - ทำหน้าที่เป็นตัวควบคุมในรูปแบบ MVC โปรแกรมเลือกจ่ายงานจะสแกนคลาสที่ทำหมายเหตุประกอบไว้สำหรับวิธีการแม็พตรวจจับคำอธิบายประกอบ @RequestMapping


-13
@Component
@Controller
@Repository
@Service
@RestController

เหล่านี้เป็นคำอธิบายประกอบ StereoType ทั้งหมดนี้มีประโยชน์สำหรับการทำให้คลาสของเราเป็นสปริงถั่วในคอนเทนเนอร์ ioc

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