Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

블로그 이름 뭐하지

[Spring] Bean 본문

Spring

[Spring] Bean

가는말이고우면오는말은come 2024. 11. 13. 16:07

이전에 작성한 Bean 관련 링크(하단 참고)

 

[Spring] IOC(제어의 역전)와 DI(의존성 주입)

제어의 역전(Inversion of Control) 개발자가 직접 제어흐름을 제어하지 않고, 외부의 프레임워크나 라이브러리가 제어 흐름을 대신하게 되는 것이다.// 클래스 A에서 new 키워드로 클래스 B의 객체 생

blognameless.tistory.com

 

Bean 수동 등록

//예시로 드는 passwordEncoder의 경우 아래와 같은 설정이 필요하다

// 1) build.gradle 의존성 설정

implementation 'org.springframework.boot:spring-boot-starter-security'
// 또는
implementation 'org.springframework.security:spring-security-core'
// 권한이나 인증관리가 필요할 때는 전자를, 단순히 비밀번호 인코딩만 필요할 때는 후자를 사용


// 2) 전자를 사용할 경우
// SpringBootApplication에 해당 코드 추가

package com.sparta.springauth;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;

@SpringBootApplication(exclude = SecurityAutoConfiguration.class) // Spring Security 인증 기능 제외
public class SpringAuthApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringAuthApplication.class, args);
    }

}

 

@Component를 사용하면 @ComponentScan에 의해 해당 클래스가 Bean으로 자동등록된다.

비즈니스 로직과 관련된 클래스들은 @Controller, @Service, @Repository 같은 애너테이션으로 자동등록한다.

이 외 공통 로그 처리와 같은 비즈니스 로직을 지원하는 부가적, 공통적인 기능을 처리할 때, Bean을 수동등록한다.

 

Bean 수동 등록 방법

1) Bean으로 등록하고자 하는 객체를 반환하는 메서드 선언 후 @Bean을 설정한다.

2) Bean을 등록하는 메서드가 속한 클래스에 @Configuration을 설정한다.

3) Spring 서버가 뜰 때, Spring IoC 컨테이너에 해당 객체가 bean으로 저장된다.

@Configuration
public class PasswordConfig {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}


// 1. @Bean 설정된 메서드 호출
PasswordEncoder passwordEncoder = passwordConfig.passwordEncoder();

// 2. Spring IoC 컨테이너에 빈 (passwordEncoder) 저장
// passwordEncoder -> Spring IoC 컨테이너

// Bean 실행
@SpringBootTest
public class PasswordEncoderTest {

    @Autowired
    PasswordEncoder passwordEncoder;

    @Test
    @DisplayName("수동 등록한 passwordEncoder를 주입 받아와 문자열 암호화")
    void test1() {
        String password = "Robbie's password";

        // 암호화
        String encodePassword = passwordEncoder.encode(password);
        System.out.println("encodePassword = " + encodePassword);

        String inputPassword = "Robbie";

        // 해시된 비밀번호와 사용자가 입력한 비밀번호를 해싱한 값을 비교
        boolean matches = passwordEncoder.matches(inputPassword, encodePassword);
        System.out.println("matches = " + matches); // 암호화할 때 사용된 값과 다른 문자열과 비교했기 때문에 false
    }
}

 

같은 타입의 Bean 등록

문제 발생

// Food Interface
public interface Food {
    void eat();
}

// Food 인터페이스를 구현한 Chicken 클래스
@Component // Bean 등록
public class Chicken implements Food {
    @Override
    public void eat() {
        System.out.println("치킨을 먹습니다.");
    }
}

// Food 인터페이스를 구현한 Pizza 클래스
@Component
public class Pizza implements Food {
    @Override
    public void eat() {
        System.out.println("피자를 먹습니다.");
    }
}

 

Food 인터페이스가 있고 그를 구현한 각각의 다른 클래스가 Bean으로 등록되어 있을 때,

Food를 주입하려고 하면 오류가 난다.

@SpringBootTest
public class BeanTest {

    @Autowired
    Food food;
    // Food 타입의 Bean 객체가 두 개 이상 존재해 주입을 할 수 없다는 오류가 난다.
   
}

 

해결방안

 

1) 등록된 Bean 이름 명시

아래와 같이 등록된 Bean의 이름을 정확히 명시하면 해결된다.

@Autowired는 기본적으로 Bean Type으로 의존성을 주입하며,

연결이 되지 않을 경우 Bean Name으로 찾기 때문이다.

@SpringBootTest
public class BeanTest {

    @Autowired
    Food pizza;
    
    @Autowired
    Food chicken;
    
}

 

2) @Primary 사용

아래와 같이 주입하고 싶은 클래스에 @Primary 키를 달면 같은 타입의 Bean 객체가 여러 개 있더라도

우선적으로 @Primary가 설정된 객체를 주입한다.

@Component
@Primary // Chicken 클래스에 Primary 어노테이션 적용
public class Chicken implements Food {
    @Override
    public void eat() {
        System.out.println("치킨을 먹습니다.");
    }
}

@SpringBootTest
public class BeanTest {
    @Autowired
    Food food; // Chicken 객체를 주입한다
}

 

3) @Qualifier 사용

객체가 여러개일 때, 식별이 모호할 경우 사용하는 어노테이션이다.

@Component
@Qualifier("pizza") // Pizza 클래스에 Qualifier 어노테이션 적용
public class Pizza implements Food {
    @Override
    public void eat() {
        System.out.println("피자를 먹습니다.");
    }
}

@SpringBootTest
public class BeanTest {

    @Autowired
    @Qualifier("pizza")// 주입하고자 하는 필드에도 @Qualifier 어노테이션 적용
    Food food;
}

 

'Spring' 카테고리의 다른 글

[Spring] 필터(Filter)  (0) 2024.11.14
[Spring] 쿠키와 세션, JWT  (0) 2024.11.13
[Spring] JPA  (0) 2024.11.13
[Spring] IOC(제어의 역전)와 DI(의존성 주입)  (0) 2024.10.10
[Spring] 3 Layer Architecture  (0) 2024.10.10