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


459

ฉันเข้าใจว่ามีการเพิ่ม@Componentคำอธิบายประกอบในฤดูใบไม้ผลิ 2.5 เพื่อกำจัดคำจำกัดความ xml bean โดยใช้การสแกนคลาสพา ธ

@Beanถูกนำมาใช้ในฤดูใบไม้ผลิ 3.0 และสามารถใช้กับ@Configurationเพื่อกำจัดไฟล์ xml อย่างสมบูรณ์และใช้การกำหนดค่า Java แทน

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


4
มีที่ไหนที่ @Bean สามารถใช้นอกเหนือจากคลาสการกำหนดค่าได้หรือไม่
Willa


@Willa ใช่มีอยู่ Lite modeที่เรียกว่า และไม่แนะนำ ดูที่นี่: docs.spring.io/spring/docs/current/spring-framework-reference/ ......
smwikipedia

8
ฉันจะสรุปว่าวิธีการที่@beanส่งคืนตัวอย่างของสปริงถั่วในขณะที่@componentกำหนดคลาสที่อาจได้รับการติดตั้งโดยเอ็นจิ้น IoC เมื่อต้องการ
Sebas

คำตอบ:


433

@Componentและ@Beanทำสองสิ่งที่แตกต่างกันมากและไม่ควรสับสน

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

@Beanใช้เพื่อประกาศถั่วเดี่ยวอย่างชัดเจนแทนที่จะปล่อยให้ Spring ทำโดยอัตโนมัติดังกล่าวข้างต้น มันแยกการประกาศของ bean จากนิยามคลาสและช่วยให้คุณสร้างและกำหนดค่าถั่วอย่างที่คุณเลือก

เพื่อตอบคำถามของคุณ ...

เป็นไปได้ไหมที่จะใช้@Componentคำอธิบายประกอบซ้ำอีกครั้งแทนที่จะใช้@Beanคำอธิบายประกอบ

แน่นอนว่าอาจ; แต่พวกเขาเลือกที่จะไม่ทำเนื่องจากทั้งสองแตกต่างกันมาก ฤดูใบไม้ผลิของความสับสนอยู่แล้วพอโดยไม่ต้องยุ่งกับน้ำต่อไป


3
ดังนั้นฉันสามารถใช้งานได้เฉพาะ@Componentเมื่อจำเป็นต้องมีการตอบรับอัตโนมัติเท่านั้น ดูเหมือนว่า@Beanจะไม่ส่งผลกระทบต่อ@Autowired
Jaskey

3
ใช้ '@component' สำหรับคลาสที่อ้างอิงเซอร์วิส '@Bean' เนื่องจากเป็นวัตถุที่สร้างขึ้นตามความต้องการของผู้ใช้เช่น jdbc datasource
Junchen Liu

2
@ Jaskey คุณสามารถใช้@Autowiredกับ@Beanถ้าคุณได้ใส่คำอธิบายประกอบคลาสของคุณด้วย@Configuration
starcorn

6
ขออภัยฉันไม่เข้าใจคำอธิบายของคุณ คุณเข้าใจเรื่องนี้ชัดเจนดังนั้นโปรดเขียนคำอธิบายที่ชัดเจนหรือชี้ไปที่เอกสารที่เหมาะสม?
Alex Worden

13
ตอนนี้ฉันเข้าใจแนวคิด (จากการอ่านคำตอบของคนอื่น) คำอธิบายของคุณสมเหตุสมผลแล้ว ซึ่งบอกฉันทั้งหมดยิ่งขึ้นว่าคำอธิบายของคุณไม่ดีสำหรับใครก็ตามที่ไม่เข้าใจแนวคิด
Alex Worden

397

@Component ดีกว่าสำหรับการสแกนส่วนประกอบและการเดินสายอัตโนมัติ

เมื่อคุณควรใช้@Bean ?

บางครั้งการกำหนดค่าอัตโนมัติไม่ใช่ตัวเลือก เมื่อไหร่? สมมติว่าคุณต้องการวางสายส่วนประกอบจากไลบรารีของบุคคลที่สาม (คุณไม่มีซอร์สโค้ดดังนั้นคุณไม่สามารถใส่คำอธิบายประกอบคลาสด้วย @Component) ดังนั้นจึงไม่สามารถกำหนดค่าอัตโนมัติได้

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


5
ฉันคิดว่านี่เป็นสิ่งที่สมเหตุสมผลที่สุด ถ้าฉันเข้าใจอย่างถูกต้อง@Componentไปเรียนในตัวเองในขณะที่@Beanไปในวิธีการเรียน (ซึ่งผลผลิตอินสแตนซ์ของวัตถุคลาส)
jocull

182

ลองพิจารณาว่าฉันต้องการการใช้งานที่เฉพาะเจาะจงขึ้นอยู่กับสถานะไดนามิกบางอย่าง @Beanเหมาะสำหรับกรณีนั้น

@Bean
@Scope("prototype")
public SomeService someService() {
    switch (state) {
    case 1:
        return new Impl1();
    case 2:
        return new Impl2();
    case 3:
        return new Impl3();
    default:
        return new Impl();
    }
}

@Componentแต่ไม่มีทางที่จะทำอย่างนั้นไม่มี


3
คุณเรียกคลาสตัวอย่างนั้นได้อย่างไร?
PowerFlower

1
@PowerFlower วิธีนี้ควรอยู่ในคลาสการกำหนดค่าซึ่งมีคำอธิบายประกอบด้วย@Configuration
Juh_

98
  1. @Component ตรวจจับและกำหนดค่าถั่วโดยใช้การสแกนคลาสพา ธ ขณะที่ @Bean ประกาศถั่วเดี่ยวอย่างชัดเจนแทนที่จะปล่อยให้ Spring ทำโดยอัตโนมัติ
  2. @Component ไม่แยกการประกาศของ bean จากนิยามคลาสโดยที่ @Bean จะแยกการประกาศของ bean จากนิยามของคลาส
  3. @Component เป็นคำอธิบายประกอบในระดับชั้นในขณะที่ @Bean เป็นคำอธิบายประกอบในระดับวิธีการและชื่อของวิธีการที่ทำหน้าที่เป็นชื่อถั่ว
  4. @Component ไม่จำเป็นต้องที่จะใช้กับ @Configurationบันทึกย่อที่เป็นคำอธิบายประกอบ @Bean จะต้องมีการใช้ในชั้นเรียนซึ่งเป็นข้อเขียนที่มี @Configuration
  5. เราไม่สามารถสร้างถั่วของการเรียนโดยใช้ @Component ถ้าชั้นเป็นภาชนะฤดูใบไม้ผลินอกในขณะที่เราสามารถสร้างถั่วของชั้นเรียนโดยใช้ @Bean แม้ว่าระดับเป็นปัจจุบันนอกภาชนะฤดูใบไม้ผลิ
  6. @Component มีความเชี่ยวชาญที่แตกต่างกันเช่น @Controller, @Repository และ @Service ขณะ @Bean มีไม่มีความเชี่ยวชาญ

3
4. จริงๆแล้ว @Bean สามารถประกาศในคลาสที่ไม่ได้กำหนดค่าได้ รู้จักกันในชื่อโหมด lite
voipp

1
เกี่ยวกับจุดที่ 5 ฉันคิดว่าเราใส่ถั่วไว้ในภาชนะสปริง ดังนั้นทุก ๆ คลาสจะอยู่นอกภาชนะสปริง ผมคิดว่าจุดที่ 5 ควรจะได้รับการตอบแทน
Eugen

97

ทั้งสองวิธีมีเป้าหมายที่จะลงทะเบียนประเภทเป้าหมายใน Spring container

ความแตกต่างคือ@Beanใช้ได้กับวิธีการในขณะที่@Componentใช้บังคับกับประเภท

ดังนั้นเมื่อคุณใช้@Beanคำอธิบายประกอบคุณสามารถควบคุมตรรกะการสร้างอินสแตนซ์ในเนื้อหาของเมธอด (ดูตัวอย่างด้านบน ) ด้วย@Componentคำอธิบายประกอบคุณไม่สามารถ


ประเภทคืออะไร
Jac Frall

20

ฉันเห็นมากของคำตอบและเกือบทุก @Component กล่าวถึงคือสำหรับ autowiring ที่องค์ประกอบที่จะถูกสแกนและ @Bean เป็นว่าประกาศถั่วที่จะใช้ที่แตกต่างกัน ให้ฉันแสดงความแตกต่าง

  • @ถั่ว

ก่อนอื่นมันเป็นคำอธิบายประกอบในระดับวิธีการ อันดับที่สองโดยทั่วไปคุณใช้เพื่อกำหนดค่า beans ในโค้ด Java (ถ้าคุณไม่ได้ใช้การกำหนดค่า xml) จากนั้นเรียกใช้จากคลาสโดยใช้เมธอด getBean ของ ApplicationContext ชอบ

 @Configuration
class MyConfiguration{
    @Bean
    public User getUser(){
        return new User();
    }
}

class User{
}



//Getting Bean 
User user = applicationContext.getBean("getUser");
  • @Component

มันเป็นวิธีทั่วไปในการใส่คำอธิบายประกอบถั่วและไม่ใช่ถั่วพิเศษ คำอธิบายประกอบในระดับชั้นเรียนและใช้เพื่อหลีกเลี่ยงสิ่งที่กำหนดค่าทั้งหมดผ่านการกำหนดค่า java หรือ xml

เราได้อะไรเช่นนี้

@Component
class User {
}

//to get Bean
@Autowired
User user;

แค่นั้นแหละ . มันเพิ่งถูกนำมาใช้เพื่อหลีกเลี่ยงขั้นตอนการกำหนดค่าทั้งหมดเพื่อยกตัวอย่างและใช้ถั่วนั้น


5
ฉันคิดว่ามันไม่จำเป็นที่จะได้รับวัตถุผู้ใช้จาก ApplicationContext เมื่อคุณใช้@Beanวิธีการ คุณยังสามารถใช้การได้รับถั่วที่คุณจะทำในกรณีของ@Autowire เพียงเพิ่ม Bean เข้ากับ Spring Container เช่นเดียวกับที่ทำ ความแตกต่างมีดังนี้ 1. การใช้คุณสามารถเพิ่มคลาสของบุคคลที่สามไปยัง Spring Container 2. การใช้คุณสามารถใช้อินเทอร์เฟซที่ต้องการได้ในขณะใช้งาน (โดยใช้รูปแบบการออกแบบจากโรงงาน)@Component@Bean@Component@Bean@Bean
Andy

20

คุณสามารถใช้@Beanเพื่อทำให้คลาสบุคคลที่สามที่มีอยู่พร้อมใช้งานกับบริบทแอปพลิเคชัน Spring Framework ของคุณ

@Bean
public ViewResolver viewResolver() {

    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

    viewResolver.setPrefix("/WEB-INF/view/");
    viewResolver.setSuffix(".jsp");

    return viewResolver;
}

โดยการใช้@Beanคำอธิบายประกอบคุณสามารถล้อมคลาสบุคคลที่สาม (อาจไม่มี@Componentและไม่สามารถใช้ Spring) เป็น Spring bean และเมื่อมันถูกห่อโดยใช้@Beanมันจะเป็นวัตถุเดี่ยวและมีอยู่ในบริบทของ Spring application application ขณะนี้คุณสามารถแบ่งปัน / นำมาใช้ถั่วนี้ใน app @Autowiredของคุณโดยใช้ฉีดพึ่งพาและ

ดังนั้นให้คิดว่า@Beanคำอธิบายประกอบนั้นเป็น wrapper / adapter สำหรับคลาสบุคคลที่สาม คุณต้องการให้คลาสบุคคลที่สามพร้อมใช้งานกับบริบทแอปพลิเคชัน Spring Framework ของคุณ

โดยใช้@Beanในรหัสข้างต้นฉันประกาศถั่วเดียวอย่างชัดเจนเพราะภายในวิธีการฉันสร้างวัตถุโดยใช้newคำหลักอย่างชัดเจน ฉันยังเรียกเมธอด setter ของคลาสที่กำหนดด้วยตนเอง ดังนั้นฉันสามารถเปลี่ยนค่าของฟิลด์คำนำหน้า ดังนั้นคู่มือนี้จึงเรียกว่าการสร้างที่ชัดเจน ถ้าฉันใช้@Componentสำหรับคลาสเดียวกัน bean ที่รีจิสเตอร์ในคอนเทนเนอร์ฤดูใบไม้ผลิจะมีค่าเริ่มต้นสำหรับฟิลด์คำนำหน้า

ในทางกลับกันเมื่อเราใส่คำอธิบายประกอบชั้นเรียนด้วย@Componentเราไม่จำเป็นต้องใช้newคำหลักด้วยตนเอง มันถูกจัดการโดยอัตโนมัติโดยสปริง


1
จะดีถ้าคำตอบนี้ได้รับการปรับปรุงด้วยตัวอย่างของวิธีการใช้ถั่วนั้นเช่นกัน
softarn

คุณจะห่อ @Bean ให้กับคลาสของบุคคลที่สามได้อย่างไรหากซอร์สโค้ดไม่อนุญาตให้มีการแก้ไข
veritas

16

เมื่อคุณใช้@Componentแท็กมันก็เหมือนกับการมี POJO (วัตถุ Java เก่าธรรมดา) ด้วยวิธีการประกาศ vanilla bean (บันทึกย่อด้วย@Bean) ตัวอย่างเช่นวิธีต่อไปนี้ 1 และ 2 จะให้ผลลัพธ์เดียวกัน

วิธีที่ 1

@Component
public class SomeClass {

    private int number;

    public SomeClass(Integer theNumber){
        this.number = theNumber.intValue();
    }

    public int getNumber(){
        return this.number;
    }
}

ด้วยถั่วสำหรับ 'theNumber':

@Bean
Integer theNumber(){
    return new Integer(3456);
}

วิธีที่ 2

//Note: no @Component tag
public class SomeClass {

    private int number;

    public SomeClass(Integer theNumber){
        this.number = theNumber.intValue();
    }

    public int getNumber(){
        return this.number;
    }
}

กับถั่วสำหรับทั้งสอง:

@Bean
Integer theNumber(){
    return new Integer(3456);
}

@Bean
SomeClass someClass(Integer theNumber){
    return new SomeClass(theNumber);
}

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

@Bean
SomeClass strawberryClass(){
    return new SomeClass(new Integer(1));
}

10

คุณมีสองวิธีในการสร้างถั่ว @Componentหนึ่งคือการสร้างชั้นที่มีคำอธิบายประกอบ อื่น ๆ @Beanคือการสร้างวิธีการและอธิบายด้วย สำหรับคลาสที่มีเมธอดด้วย@Beanควรถูกใส่หมายเหตุประกอบด้วย@Configuration เมื่อคุณรันโปรเจ็กต์ฤดูใบไม้ผลิคลาสที่มี@ComponentScanคำอธิบายประกอบจะสแกนทุกคลาสด้วย@Componentและเรียกคืนอินสแตนซ์ของคลาสนี้ไปยังคอนเทนเนอร์ Ioc อีกสิ่งที่@ComponentScanจะทำคือการเรียกใช้เมธอดด้วย@Beanและเรียกคืนออบเจ็กต์คืนไปยัง Ioc Container เป็น bean ดังนั้นเมื่อคุณต้องตัดสินใจว่าคุณต้องการสร้างถั่วชนิดใดขึ้นอยู่กับสถานะปัจจุบันคุณต้องใช้@Bean. คุณสามารถเขียนตรรกะและส่งคืนวัตถุที่คุณต้องการ สิ่งที่ควรค่าแก่การพูดถึงคือชื่อของเมธอดที่มี@Beanคือชื่อดีฟอลต์ของ bean


6
  • @component และความเชี่ยวชาญ (@Controller, @service, @repository) ช่วยให้สามารถตรวจจับอัตโนมัติโดยใช้การสแกนคลาสพา ธ หากเราเห็นคลาสคอมโพเนนต์เช่น @Controller, @service, @repository จะถูกสแกนโดยอัตโนมัติโดยเฟรมเวิร์กสปริงโดยใช้การสแกนคอมโพเนนต์
  • @Bean ในอีกทางหนึ่งสามารถใช้เพื่อประกาศถั่วเดี่ยวอย่างชัดเจนในคลาสการกำหนดค่า
  • @Bean ใช้เพื่อประกาศถั่วเดี่ยวอย่างชัดเจนแทนที่จะปล่อยให้สปริงทำโดยอัตโนมัติ ทำให้การประกาศ septate ของถั่วจากคำจำกัดความของชั้นเรียน
  • ในระยะสั้น @Controller, @service, @repository สำหรับการตรวจจับอัตโนมัติและ @Bean เพื่อสร้างถั่ว seprate จากคลาส
    - @Controller
    LoginController ระดับสาธารณะ 
    {--code--}

    - การกำหนดค่า @
    AppConfig ระดับสาธารณะ
    @ถั่ว
    สาธารณะ SessionFactory sessionFactory () 
    {--code--}

3

@Bean ถูกสร้างขึ้นเพื่อหลีกเลี่ยงข้อต่อ Spring และกฎเกณฑ์ทางธุรกิจของคุณในเวลารวบรวม หมายความว่าคุณสามารถใช้กฎธุรกิจของคุณในกรอบอื่น ๆ เช่น PlayFramework หรือ JEE

นอกจากนี้คุณมีการควบคุมทั้งหมดเกี่ยวกับวิธีการสร้าง beans โดยที่ไม่เพียงพอสำหรับการเริ่มต้นการเริ่มต้นฤดูใบไม้ผลิ

ฉันเขียนโพสต์ที่พูดถึงมัน

https://coderstower.com/2019/04/23/factory-methods-decoupling-ioc-container-abstraction/



1

1. เกี่ยวกับ @Component @Component ฟัง
ก์ชั่นคล้ายกับ @Configuration พวกเขาทั้งสองแสดงให้เห็นว่าระดับข้อเขียนมีหนึ่งหรือมากกว่าถั่วจะต้องมีการลงทะเบียนกับ

ชั้นข้อเขียน @Component เราเรียกว่า มันเป็นแนวคิดที่มีหลายถั่ว จะต้องอัตโนมัติสแกนโดยฤดูใบไม้ผลิสำหรับการลงทะเบียนถั่วบรรดาของSpring-IOC-Container

Component of Spring

Component classcomponent class

2. เกี่ยวกับ @Bean
@Bean ใช้เพื่ออธิบายวิธีการของcomponent-class(ตามที่กล่าวไว้ข้างต้น) มันแสดงให้เห็นเช่น retured Spring-IOC-Containerด้วยวิธีข้อเขียนจะต้องลงทะเบียนกับ

3. สรุป
ความแตกต่างระหว่างพวกเขาทั้งสองค่อนข้าง obivious different circumstancesพวกเขาจะใช้ใน การใช้งานทั่วไปคือ:

    // @Configuration is implemented by @Component
    @Configuration
    public ComponentClass {

      @Bean
      public FirstBean FirstBeanMethod() {
        return new FirstBean();
      }

      @Bean
      public SecondBean SecondBeanMethod() {
        return new SecondBean();
      }
    }

0

คะแนนเพิ่มเติมจากคำตอบข้างต้น

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

หากใช้ @Component ในคลาสบริการเหล่านั้นและการสแกนส่วนประกอบในแอปพลิเคชัน

เราอาจพบการตรวจพบถั่วมากกว่าที่จำเป็น

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

ในกรณีนี้จะเป็นการดีกว่าถ้าคุณทำงานกับคำอธิบายประกอบ @Bean และสร้างอินสแตนซ์ของถั่วเหล่านั้นเท่านั้น

ซึ่งจำเป็นต้องใช้แยกต่างหากในแต่ละแอป

ดังนั้นโดยพื้นฐานให้ใช้ @Bean เพื่อเพิ่มคลาสบุคคลที่สามให้กับบริบท และ @Component หากอยู่ภายในแอปพลิเคชันเดียวของคุณ

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