250117 TIL

2025. 1. 17. 17:08·TIL

 IoC 컨테이너는 객체를 빈이라는것으로 관리를 한다?

컨테이너에 객체(빈)를 등록하여 컨테이너가 객체를 사용하는 권한을 가진다?

컨테이너 안 객체들 사이에 의존성을 주입 하여 객체들 간의 관계를 정리한다?

IoC (Inversion of Control, 제어의 역전)

👉🏻애플리케이션의 제어 권한을 개발자(혹은 프로그램 코드)에서 프레임워크나 컨테이너(SPRING)로 넘기는 것

Spring에서는 IoC를⭐DI (Dependency Injection)⭐ 방식을 통해 구현

 

Spring의 IoC 컨테이너를 이용하여 Bean을 등록하는 방법

1️⃣ XML 파일을 이용한 Bean 등록

2️⃣ Java Config 클래스를 이용한 Bean 등록: @Configuration과 @Bean을 사용하여 빈을 등록 ▶️외부 객체 

3️⃣ 애노테이션을 이용한 Bean 등록: @Component, @Service, @Controller, @Repository 등을 사용하여 Bean을 정의하고, @ComponentScan으로 Bean을 스캔 ▶️ 자신이 만든 객체

 

➕@SpringBootApplication 사용 시 기본 스캔

  • Spring Boot 애플리케이션에서 @SpringBootApplication 어노테이션이 붙은 클래스가 자동으로 컴포넌트를 스캔
  • @SpringBootApplication은 기본적으로 현재 클래스가 위치한 패키지와 그 하위 패키지를 스캔.

 

DI (Dependency Injection, 의존성 주입)

👉🏻객체 간의 의존 관계를 Spring 컨테이너가 설정하고 주입하는 것

 

▪️객체를 생성할 때 필요한 의존성을 직접 생성하는 대신 외부에서 주입 받음

➡️객체 변경 시 객체를 사용하는 쪽에서 객체를 변경하는 것이 아니라 외부에서 변경함

 

▪️장점

👍🏻객체 간 결합도를 줄여 유연성과 재사용성 높다

👍🏻객체 간의 관계를 명확히 하여 코드 유지보수 용이

DI의 방식

1️⃣필드 주입 (Field Injection) (비추천. 스프링에 의존적)

@Autowired를 사용하여 클래스의 필드에 의존성을 직접 주입

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
}

 

2️⃣생성자 주입 (Constructor Injection) (추천) 생성자가 하나뿐일 때는 @Autowired 생략 가능.

@Service
public class UserService {
    private final UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

 

3️⃣Setter 주입 (Setter Injection)

@Service
public class UserService {
    private UserRepository userRepository;

    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

 

 


 

🔹@Component: Spring이 관리할 일반적인 빈(Bean)을 등록

@Component //기본은 생성자 주입
public class Dice {
    private int face;
    
    public Dice() {
        System.out.println("Dice Constructor");
    }
    public Dice(int face) {
        this.face = face;
        System.out.println("Dice Constructor(int) 실행");
    }

    public int getNumber(){
        return (int)(Math.random()*face)+1;
    }
}
@Component
public class Game {
    private List<Player> list; //플레이어 리스트도 스프링 공장을 통해서 생성, 주입 받음

    public Game() {

    }
    public Game(List<Player> list) {
        System.out.println("Game(List<Player>) list 생성자 실행");
        this.list = list;
    }

    public void setList(List<Player> list) {
        this.list = list;
    }

    public void play(){
        for(Player player : list){
            player.play();
        }
    }
}

 

▫️ @component(”id”) id를 등록

▫️ 아무것도 안쓰면 클래스이름의 첫 글자를 소문자로 바꾼 아이디로 설정

@Component("bbb")//id는 bbb로 등록 아무것도 안쓰면 클래스이름의 첫 글자를 소문자로 바꾼 아이디로 설정 됨
public class Book {
    private String title;
    private int price;

    public Book() {
        System.out.println("Book 생성");
    }
}

 

🔹 @Component 사용 안하고 수동으로 빈을 등록 할 수도 있음

public class Player {
    private String name;
    private Dice dice; //실행 될 때 주사위를 주입 받아야 함 (의존성 주입 DI)

    public Player() {

    }
    public Player(Dice dice) {
        this.dice = dice;
    }

    public void setDice(Dice dice) {
        this.dice = dice;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void play() {
        System.out.println(name+"은 주사위를 던져서"+dice.getNumber()+"가 나왔습니다");
    }
}

 

🔹 @ComponentScan 을 사용하여 @@Component가 붙은 빈들을 등록

🔹 basePackages = "" 스캔 할 패키지 지정

@ComponentScan(basePackages = "sample") //sample 패키지 아래
@PropertySource({"classpath:game.properties"})//이 파일의 설정 사용 
public class GameConfig {

//    @Bean
//    public Dice dice(@Value("${face}")int face) {
//        return new Dice(face);
//    }
    @Bean
    public Player kang(Dice d) {
        //Player player=new Player(d); 생성자 주입
        Player player = new Player();
        player.setDice(d);
        player.setName("Kang");
        return player;
    }

    @Bean
    public Player hwang(Dice d) {
        //Player player=new Player(d); 생성자 주입
        Player player = new Player();
        player.setDice(d);
        player.setName("hwang");
        return player;
    }
    @Bean
    public Player kim(Dice d) {
        //Player player=new Player(d); 생성자 주입
        Player player = new Player();
        player.setDice(d);
        player.setName("kim");
        return player;
    }

    @Bean
    public Game game(List<Player> players) {
        Game game = new Game();
        game.setList(players);
        return game;

    }

}

 

🔹 resource → game.properties 생성하여 face 값을 생성

face=45
public class SpringExam02 {
    public static void main(String[] args) {
        ApplicationContext context=new AnnotationConfigApplicationContext(GameConfig.class);

        Game game=context.getBean("game", Game.class);

        game.play();
        
        Book book=context.getBean("bbb",Book.class); //Book이라는 클래스에 @Component 사용해서 자동으로 빈 등록이 됨
        //GameConfig 컨테이너에서 이를 감지해 빈을 가져옴 

        MyBean myBean=context.getBean(MyBean.class);
        myBean.setName("jiyun");
        System.out.println(myBean.getName());

    }
}
ApplicationContext context = new AnnotationConfigApplicationContext(GameConfig.class);

 

▫️Spring 컨테이너를 초기화하며, 설정 클래스로 GameConfig.class를 사용 GameConfig는 Java Config 방식으로 Spring에서 사용할 Bean을 정의한 클래스

Game game = context.getBean("game", Game.class);
game.play();

 

▫️ game이라는 이름으로 등록된 Game 타입의 Bean을 가져옴

 

🔹 수동으로 빈 등록 시

public class MyBeanConfig {
    //스프링 공장에게 어떤 빈을 관리하게 할것인지 알려줘야 함
    //XML
    //<bean id="myBean" class = "sample.been.MyBeen"/>
    //기본 설정이 싱글턴
    //아이디가 다르면 다른 객체 생성
    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
    @Bean
    public MyBean myBean2() {
        return new MyBean();
    }

    @Bean
    @Scope("prototype") // 매번 다른 객체가 생성
    public MyBean myBean3() {
        return new MyBean();
    }

    @Bean
    public Book book() {
        return new Book();
    }

}

 

▫️ 기본적으로 같은 아이디를 써서 생성한 빈은 싱글턴 객체이다

 빈 공장이 생성 될 때 객체가 생성되고 객체가 불릴 때 이미 생성된 객체를 리턴해줌   

▫️ 다른 아이디로 생성한 빈은 다른 객체

▫️ @Scope("prototype")을 설정한 빈은 생성될 때 마다 매번 다른 객체가 생성 된다

빈 공장이 생성 될 때 생기지 않고 객체가 불릴 때 마다 객체를 생성해서 리턴 해줌 

public class SpringExam01 {
    public static void main(String[] args) {
        //직접 사용하는 경우
        MyBean bean = new MyBean();
        bean.setName("abd");

        System.out.println(bean.getName());

 
        //스프링이 제공하는 공장을 통해서 사용
        //1.BeanFactory --단순한 일만 한다 AOP 같은 기술은 사용할 수 없다

        ApplicationContext context = new AnnotationConfigApplicationContext(MyBeanConfig.class);

        MyBean bean1 = (MyBean) context.getBean("myBean"); //lookup 방식

        MyBean bean2 = context.getBean("myBean",MyBean.class); //lookup 방식+형변환 안해도 됨

        if(bean1==bean2) {
            System.out.println("같은 인스턴스 입니다");
        }else{
            System.out.println("다른 인스턴스 입니다");
        }

        MyBean bean3 = context.getBean("myBean2",MyBean.class);
        if(bean3==bean2) {
            System.out.println("같은 인스턴스 입니다");
        }else{
            System.out.println("다른 인스턴스 입니다");
        }

        MyBean bean4 = (MyBean) context.getBean("myBean3",MyBean.class);
        MyBean bean5 = (MyBean) context.getBean("myBean3",MyBean.class);

        if(bean4==bean5) {
            System.out.println("bean4 == bean5 같은 인스턴스");
        }else {
            System.out.println("bean4 != bean5 다른 인스턴스");
        }

        //id 없이 타입만 가지고 룩업 해줌
        //이 타입의 빈이 하나만 있어야함
        Book book = context.getBean(Book.class);
        System.out.println(book);

    }
 
어노테이션 역할 및 용도
@Component 일반적인 Spring Bean으로 등록. 주로 서비스, 유틸리티 클래스를 Bean으로 관리.
@Service 비즈니스 로직 계층을 나타내는 Bean. 기능적으로 @Component와 동일하나 의미적으로 구분.
@Repository DAO(Data Access Object) 계층. 예외 변환과 같은 추가 기능 제공.
@Controller Spring MVC에서 HTTP 요청을 처리하는 컨트롤러 클래스를 나타냄.
@RestController REST API를 처리하는 컨트롤러. @Controller와 @ResponseBody를 결합한 형태.
@Configuration Java 기반 설정 클래스를 나타냄. Bean 정의 메서드를 포함.
@Bean Java Config에서 Bean을 정의하는 메서드에 사용. 반환된 객체가 Spring 컨테이너에 등록됨.
@ComponentScan 지정된 패키지에서 @Component, @Service, @Repository, @Controller 등을 스캔하여 Bean 등록.

 

'TIL' 카테고리의 다른 글

250121 TIL  (1) 2025.01.22
250120 TIL  (4) 2025.01.21
250116 TIL  (0) 2025.01.16
250110 TIL  (0) 2025.01.10
250109 TIL  (5) 2025.01.09
'TIL' 카테고리의 다른 글
  • 250121 TIL
  • 250120 TIL
  • 250116 TIL
  • 250110 TIL
Jiyuuuuun
Jiyuuuuun
  • Jiyuuuuun
    Hello, World!
    Jiyuuuuun
  • 전체
    오늘
    어제
    • 분류 전체보기 (112)
      • TIL (56)
      • CS (17)
        • Network (4)
        • Algorithm (10)
      • JAVA (5)
      • Project (10)
        • HakPle (3)
        • JUSEYO (4)
      • Spring (2)
      • C (3)
      • C++ (16)
      • Snags (2)
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    java
    Docker
    Kubernetes
    db
    hakple
    SQL
    nginx
    node.js
    juseyo
    멋쟁이사자처럼
    JDBC
    javascript
    CSS
    JPA
    my_favorite_place
    부트캠프
    front-end
    HTML
    back-end
    react
    springboot
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Jiyuuuuun
250117 TIL
상단으로

티스토리툴바