
알고 있어야할 어노테이션들 - 3
설정 관련
@Configuration 과 @Bean
설정 관련 클래스를 스프링 컨테이너에 선언할 때 사용
@Configuration
public class AppConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
// 이렇게 등록한 설정부는
// Spring을 시작 -> @Configuration 이 붙은 클래스를 찾고
// @Bean 이 붙은 메서드를 실행하고 반환 값을 컨테이너에 등록한다
// 이렇게 @Bean 이 붙은 메서드를 통해 바로 객체를 꺼내 쓸 수 있다
passwordEncoder pe1 = context.getBean(passwordEncoder.class);
passwordEncoder pe2 = context.getBean(passwordEncoder.class);
// pe1 과 pe2는 동일하다 (싱글톤 패턴)
// 다른 곳에서 사용할 때는 @AutoWired 로 주입 가능@Component와 차이점
클래스를 가져다 등록할 때 사용 → @Component
메서드의 반환 객체를 등록할 때 → @Bean
@Value 와 @ConfigurationProperties
설정 파일 내 값을 사용할 때 (값을 직접 꺼내 부여 또는 그룹으로 관리해서 부여)
@Component
public class AppInfo {
@Value("${app.name:testing}")
private String appName;
}
// application.yml
// app.name: MyApp
// application.yml 같은 설정 파일 내에 app.name의 값을 꺼내어 appName에 할당
// 기본값을 사용하는 :, 없다면 testing@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
private String name;
private String version;
}
// application.yml
// app:
// name: MyApp
// version: 1.0.0
// prefix 가 app 인 설정 그룹을 가져와서 그 안의 name과 version 을 값 사용트랜잭션 관련
@Transactional
메서드의 실행을 트랜잭션 안에서 관리
@Service
public class OrderService {
@Transactional
public Order createOrder(OrderRequest request) {
// 1. 재고 감소
productRepository.decreaseStock(productId, quantity);
// 2. 주문 생성
Order order = orderRepository.save(new Order(...));
// 3. 포인트 적립
pointRepository.addPoint(userId, points);
return order;
}
}
// 이러면 재고 감소, 주문 생성, 포인트 적립의 모든 실행이 전부 무사해야 커밋됨
// 하나라도 실패시 전부 롤백
// 이게 메서드 단위가 아니라 @Transactional 단위 임을 유의
// 다만 UnChecked Exception만 걸러내주므로
// Checked Exception이 발생해도 롤백해주려면
// @Transactional(rollbackFor = Exception.class) 사용
// 반대로 특정 Exception 은 허용시 (noRollbackFor = ..Exception.class)언급한 @Transactional 단위, 즉 전파의 단위도 설정할 수 있다
// 1. REQUIRED (기본값) - 기존 트랜잭션에 참여
@Transactional(propagation = Propagation.REQUIRED)
// 2. REQUIRES_NEW - 새 트랜잭션 생성 (독립적)
// -> 행동 로그, 에러 로그, 통계 데이터 등 메인 작업 실패시에도
// 로그는 남아야할 경우에 사용
@Transactional(propagation = Propagation.REQUIRES_NEW)
// 3. MANDATORY - 트랜잭션 필수 (없으면 예외)
@Transactional(propagation = Propagation.MANDATORY)
// 3-1. NEVER - 트랜잭션이 없는 상태에서만 실행
@Transactional(propagation = PropagationNEVER)
// 4. NOT_SUPPORTED - 트랜잭션 없이 실행
@Transactional(propagation = Propagation.NOT_SUPPORTED)
// 5. SUPPORTS - 부모 트랜잭션이 있으면 참여, 없으면 그냥 실행
// -> READ-ONLY 메서드에 주로 사용
@Transactional(propagation = Propagation.SUPPORTS)
//-------------------------------------------------------
@Service
public class OrderService {
@Autowired
private EmailService emailService;
@Transactional
public Order createOrder() {
// 주문 로직 (트랜잭션 O)
Order order = orderRepository.save(...);
// 이메일 발송 (트랜잭션 X)
emailService.sendOrderEmail(order);
return order;
}
}
@Service
public class EmailService {
// 이메일은 트랜잭션 불필요
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void sendOrderEmail(Order order) {
// 이메일 실패해도 주문은 유지됨
emailClient.send(...);
}
}Share article