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

Spring Boot ช่วยเราจัดการเรื่องเหล่านี้ให้ง่ายขึ้นโดยการสร้างออบเจกต์ที่จำเป็นตั้งแต่ขั้นตอนการเริ่มต้นใช้งานแอพพลิเคชั่นและเก็บออบเจกต์ที่สร้างขึ้นมารวมกันเอาไว้ในรูปแบบที่เรียกว่าคอนเทนเนอร์ (container) และเมื่อออบเจกต์ใดต้องการใช้งานออบเจกต์อื่นก็จะมาเรียกใช้ออบเจดต์จากคอนเทนเนอร์โดยไม่จำเป็นต้องสร้างออบเจกต์ขึ้นมาใหม่เอง เราเรียกออบเจกต์ต่างๆที่อยู่ในคอนเทนเนอร์ว่าบีน (bean) ส่วนคอนเทนเนอร์จะเป็น IoC container โดย IoC ย่อมาจาก inversion of control หมายถึงการกลับข้างกันของการควบคุม

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

เราบอกว่าออบเจกต์ใดที่เราต้องการให้เป็นบีนได้โดยการกำกับด้วย @Component และเมื่อ Spring Boot เรียกแอพพลิเคชั่นขึ้นมาทำงานจะมองหาคลาสที่กำกับด้วย @Component และสร้างออบเจกต์ขึ้นมาอย่างน้อยหนึ่งออบเจกต์และเก็บเอาไว้ในคอนเทนเนอร์ ออบเจกต์หรือบีนที่ถูกสร้างขึ้นมาจะเป็นออบเจกต์แบบ singleton ส่วนการเรียกใช้งานบีนที่อยู่ในคอนเทนเนอร์โดยบีนอื่นจะกำกับด้วย @Autowired ในคลาสที่ต้องการใช้งานเพื่อบอก Spring Boot ถึงจุดที่ต้องการใช้งานบีน ตัวอย่างเช่น เรากำหนดให้คลาส InkSupply เป็นบีน และเรียกใช้บีนในคลาส Printer ซึ่งจากตัวอย่างจะแสดงให้เห็นทั้งการเรียกใช้ผ่านเมธอดคอนสตรัคเตอร์และฟิลด์ แต่แนะนำให้เรียกใช้ผ่านเมธอดคอนสตรัคเตอร์มากกว่า เพราะชัดเจนกว่า ช่วยในเรื่องความปลอดภัยของเธรด และทำให้การทดสอบง่ายขึ้น

@Component // << บอก Spring Boot ว่าคลาสนี้เป็นบีน
public class InkSupply {

    private final String INK_MESSAGE = “This is ink supply”;

    public InkSupply() {
    }
    
    public String getMessage(){
        return INK_MESSAGE;
    }
}

@Component // << บอก Spring Boot ว่าคลาสนี้เป็นบีน
public class Printer {

    private InkSupply inkSupply;

    @Autowired // << บอก Spring Boot ว่าบีนถูกใช้ผ่านเมธอดคอนสตรัคเตอร์ตรงนี้ (inject to constructor)
    public Printer(InkSupply inkSupply) {
        this.inkSupply = inkSupply;
    }

    public void printHello(){
        System.out.println(inkSupply.getMessage());
    }
}

หรือ

@Component // << บอก Spring Boot ว่าคลาสนี้เป็นบีน
public class Printer {

    @Autowired // << บอก Spring Boot ว่าบีนถูกใช้ผ่านฟิลด์ตรงนี้ (inject to field)
    private InkSupply inkSupply;

    public void printHello(){
        System.out.println(inkSupply.getMessage());
    }
}

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

// ไม่สามารถกำหนด @Component ได้เนื่องจากไม่ใช่คลาสที่เราเขียนขึ้นมาเอง
public class InkSupply {

    private final String INK_MESSAGE = “This is ink supply”;

    public InkSupply() {
    }

    public String getMessage(){
        return INK_MESSAGE;
    }
}

//สร้างคลาสขึ้นมาเพื่อสร้างออบเจกต์จากคลาส InkSupply และกำกับคลาสด้วย @Configuration และกำกับเมธอดที่ใช้
//สร้างออบเจกต์ด้วย @Bean

@Configuration
public class PrinterConfiguration {

    @Bean
    public InkSupply getInkSupply(){
        InkSupply inkSupply = new InkSupply();
        //setting something in the inkSupply
        return inkSupply;
    }

}

@Component
public class Printer {

    private InkSupply inkSupply;

    @Autowired // <– จากนั้นเรียกใช้บีนตามปรกติ
    public Printer(InkSupply inkSupply) {
        this.inkSupply = inkSupply;
    }
}