Back-end

[Spring] μ˜μ‘΄μ„± μ£Όμž… μ‹œ @Autowired보닀 μƒμ„±μž μ£Όμž…μ„ ꢌμž₯ν•˜λŠ” 이유

μ„œμ±„λ¦¬ 2024. 2. 28. 18:16

🌏 μ˜μ‘΄μ„± μ£Όμž… 방법

  1. μƒμ„±μž μ£Όμž…(Constructor Injection)
  2. ν•„λ“œ μ£Όμž…(Field Injection)
  3. μˆ˜μ •μž μ£Όμž…(Setter Injection)

1️⃣ μƒμ„±μž μ£Όμž…(Constructor Injection)

μƒμ„±μž μ£Όμž… 방법은 μƒμ„±μžλ₯Ό 톡해 의쑴 관계λ₯Ό μ£Όμž…ν•œλ‹€.

μƒμ„±μž μ£Όμž…μ€ μƒμ„±μžμ˜ 호좜 μ‹œμ μ— 1회 호좜 λ˜λŠ” 것이 보μž₯되기 λ•Œλ¬Έμ— μ£Όμž…λ°›μ€ 객체가 λ³€ν•˜μ§€ μ•Šκ±°λ‚˜, λ°˜λ“œμ‹œ 객체의 μ£Όμž…μ΄ ν•„μš”ν•œ κ²½μš°μ— κ°•μ œν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•  수 μžˆλ‹€.

@Service
public class ProductService {
    // final을 뢙일 수 있음
    private final ProductRepository productRepository;

    @Autowired	// μƒλž΅ κ°€λŠ₯
    public ProductRepository(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }
}

Spring ν”„λ ˆμž„μ›Œν¬μ—μ„œλŠ” μƒμ„±μž μ£Όμž…μ„ 적극 지원해 μƒμ„±μžκ°€ 1개만 μžˆμ„ κ²½μš°μ— @Autowiredλ₯Ό μƒλž΅ν•΄λ„ μ£Όμž…μ΄ κ°€λŠ₯ν•˜λ„λ‘ νŽΈμ˜μ„±μ„ μ œκ³΅ν•˜κ³  μžˆλ‹€.

 

λ³΄λ„ˆμŠ€ 이득은 final ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•΄ ν•œ 번 μ΄ˆκΈ°ν™”λœ 값이 이후 변경될 수 없도둝 보μž₯ν•  수 μžˆλ‹€λŠ” 것이닀.

μƒμ„±μž μ£Όμž…μ€ 클래슀(객체)κ°€ 생성될 λ•Œ, μ˜μ‘΄μ„±μ΄ ν•¨κ»˜ μ£Όμž…λœλ‹€. 이 λ•Œ, μƒμ„±μžλ₯Ό 톡해 ν•„λ“œμ— 값을 ν• λ‹Ήν•΄ ν•œ 번 값이 μ„€μ •λœ ν›„μ—λŠ” λ³€κ²½λ˜μ§€ μ•Šκ²Œλ” final을 μ‚¬μš©ν•  수 μžˆλ‹€.

ν•˜μ§€λ§Œ μˆ˜μ •μž μ£Όμž…μ΄λ‚˜ ν•„λ“œ μ£Όμž…μ—μ„œλŠ” 클래슀 μΈμŠ€ν„΄μŠ€κ°€ λ¨Όμ € μƒμ„±λœ 후에, λ‚˜μ€‘μ— μ£Όμž…μ΄ 이루어진닀. final ν•„λ“œλŠ” μ„ μ–Έκ³Ό λ™μ‹œμ— μ΄ˆκΈ°ν™”λ˜κ±°λ‚˜, μƒμ„±μžμ—μ„œ μ΄ˆκΈ°ν™”λ˜μ–΄μ•Ό ν•œλ‹€. ν•˜μ§€λ§Œ ν•„λ“œ μ£Όμž…μ΄λ‚˜ μˆ˜μ •μž μ£Όμž… 방식은 μ•žμ„œ λ§ν•œ 것 처럼 ν΄λž˜μŠ€κ°€ 이미 μƒμ„±λœ 이후에 μ˜μ‘΄μ„±μ΄ μ£Όμž…λ˜κΈ° λ•Œλ¬Έμ—, 이 μ‹œμ μ— final을 μ‚¬μš©ν•  수 μ—†λ‹€.

 

2️⃣ μˆ˜μ •μž μ£Όμž…(Setter Injection)

μˆ˜μ •μž μ£Όμž… 방법은 ν•„λ“œ 값을 λ³€κ²½ν•˜λŠ” Setter λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ μ˜μ‘΄μ„±μ„ μ£Όμž…ν•œλ‹€.

Setter μ£Όμž…μ€ λ§Œλ“€μ–΄μ§„ 객체λ₯Ό 톡해 μ—¬λŸ¬λ²ˆ 호좜이 κ°€λŠ₯ν•˜λ―€λ‘œ μƒμ„±μž μ£Όμž…κ³Ό λ‹€λ₯΄κ²Œ 1회 ν˜ΈμΆœμ„ 보μž₯ν•˜μ§€ λͺ»ν•œλ‹€.

μ£Όμž…λ°›λŠ” 객체가 변경될 κ°€λŠ₯성이 μžˆλŠ” κ²½μš°μ— μ‚¬μš©ν•œλ‹€. (μ‹€μ œλ‘œ 변경이 ν•„μš”ν•œ κ²½μš°λŠ” 극히 λ“œλ¬Όλ‹€.)

@Service
public class ProductService {
    private ProductRepository productRepository;

    @Autowired
    public setProductRepository(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }
}

μˆ˜μ •μž μ£Όμž… 방식은 @Autowired둜 μ£Όμž…ν•  λŒ€μƒμ΄ μ—†λŠ” 경우 였λ₯˜κ°€ λ°œμƒν•œλ‹€.

μ£Όμž…ν•  λŒ€μƒμ΄ 없어도 λ™μž‘ν•˜λ„λ‘ ν•˜λ €λ©΄ @Autowired(required = false)λ₯Ό 톡해 μ„€μ •ν•  수 μžˆλ‹€.

 

3️⃣ ν•„λ“œ μ£Όμž…(Field Injection)

ν•„λ“œ μ£Όμž… 방법은 ν•„λ“œμ— 직접 μ˜μ‘΄μ„±μ„ λΆ€μ—¬ν•˜λŠ” 방법이닀.

ν•„λ“œ μ£Όμž… 방법을 μ‚¬μš©ν•˜λ©΄ μ½”λ“œκ°€ κ°„κ²°ν•΄μ§€μ§€λ§Œ μ™ΈλΆ€μ—μ„œ 접근이 λΆˆκ°€λŠ₯ν•˜λ‹€λŠ” 단점이 μžˆλ‹€.

μ΄λŠ” ν…ŒμŠ€νŠΈ μ½”λ“œμ˜ μ€‘μš”μ„±μ΄ 뢀각됨에 따라 ν•„λ“œμ˜ 객체λ₯Ό μˆ˜μ •ν•  수 μ—†λŠ” ν•„λ“œ μ£Όμž…μ€ 거의 μ‚¬μš©λ˜μ§€ μ•Šκ²Œ λ˜μ—ˆλ‹€.

(ν•„λ“œ μ£Όμž…μ€ μ˜μ‘΄μ„±μ„ μ§μ ‘μ μœΌλ‘œ μ£Όμž…λ°›κΈ° λ•Œλ¬Έμ—, ν…ŒμŠ€νŠΈ μ‹œ λͺ¨μ˜(mock) 객체λ₯Ό μ‰½κ²Œ μ£Όμž…ν•  수 μ—†μ–΄ ν…ŒμŠ€νŠΈ μž‘μ„±μ΄ μ–΄λ €μ›Œμ§„λ‹€.)

 

@Service
public class ProductService {

    @Autowired
    private ProductRepository productRepository;
    
}

 

IntelliJμ—μ„œ ν•„λ“œ μ£Όμž…μ„ μ‚¬μš©ν•˜λ©΄ Field injection is not recommended μ΄λΌλŠ” κ²½κ³  문ꡬ가 λ°œμƒν•œλ‹€.

Spring Team recommends: “Always use constructor based dependency injection in your beans. Always use assertions for mandatory dependencies”.

핡심은 μƒμ„±μž μ£Όμž… 방식을 μ΄μš©ν•˜λΌλŠ” 것인데, Spring Teamμ—μ„œ μƒμ„±μž μ£Όμž… 방식을 ꢌμž₯ν•˜λŠ” μ΄μœ λŠ” λ¬΄μ—‡μΌκΉŒ?

 

🌏 μ™œ μƒμ„±μž μ£Όμž… 방식이 ꢌμž₯λ˜λŠ”λ°?

  1. μˆœν™˜ μ°Έμ‘° λ°©μ§€
    • μ• ν”Œλ¦¬μΌ€μ΄μ…˜ ꡬ동 μ‹œμ μ— μˆœν™˜ μ°Έμ‘° μ—λŸ¬ 예방 κ°€λŠ₯
  2. ν…ŒμŠ€νŠΈ 용이
    • λ‹¨μˆœ POJOλ₯Ό μ΄μš©ν•œ ν…ŒμŠ€νŠΈ μ½”λ“œ μž‘μ„± κ°€λŠ₯
  3. μŠ€ν”„λ§μ— 독립적인 μ½”λ“œ μž‘μ„±
  4. 객체 λΆˆλ³€μ„±(Immutability) 확보
    • μ‹€ν–‰ 쀑에 객체가 λ³€ν•˜λŠ” 것 λ°©μ§€
      → 였λ₯˜ 사전 λ°©μ§€
  5. final ν‚€μ›Œλ“œ μž‘μ„± λ° Lombok과의 κ²°ν•©

 

🌱 μˆœν™˜ μ°Έμ‘° λ°©μ§€

μƒμ„±μž μ£Όμž… μ‚¬μš© μ‹œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ ꡬ동 μ‹œμ (객체의 생성 지점)에 μˆœν™˜ μ°Έμ‘° μ—λŸ¬λ₯Ό μ˜ˆλ°©ν•  수 μžˆλ‹€.

 

예λ₯Όλ“€μ–΄ λ‹€μŒκ³Ό 같이 ν•„λ“œ μ£Όμž…μ„ μ‚¬μš©ν•΄ μ„œλ‘œ ν˜ΈμΆœν•˜λŠ” μ½”λ“œκ°€ μžˆλ‹€.

@Service
public class ProductService {

    @Autowired
    private ReviewService reviewService;

    @Override
    public List<Review> getReview(Long productId) {
        return reviewService.getReview(productId);
    }
}

 

ProductServiceκ°€ 이미 ReviewService에 μ˜μ‘΄ν•˜κ³  μžˆλŠ”λ°, ReviewService도 ProductService에 μ˜μ‘΄ν•˜κ³  μžˆλ‹€.

@Service
public class ReviewService {

    @Autowired
    private ProductService productService;

    @Override
    public List<Review> getProductReview(Long productId) {
        return productService.getReview(productId);
    }
}

μœ„μ˜ 두 λ©”μ„œλ“œλŠ” μ„œλ‘œλ₯Ό 계속 ν˜ΈμΆœν•  것이고, λ©”λͺ¨λ¦¬μ— ν•¨μˆ˜μ˜ CallStack이 계속 μŒ“μ—¬ StackOverflow μ—λŸ¬κ°€ λ°œμƒν•˜κ²Œ λœλ‹€.

Caused by: java.lang.StackOverflowError: null
	at com.example.ProductService.getReview(ProductService.java:20) ~[main/:na]
	at com.example.ReviewService.getProductReview(ReviewService.java:14) ~[main/:na]
	at com.example.ProductService.getReview(ProductService.java:20) ~[main/:na]
	at com.example.ReviewService.getProductReview(ReviewService.java:14) ~[main/:na]

λ¬Έμ œλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ 아무 였λ₯˜κ°€ κ²½κ³  없이 ꡬ동돼 μ‹€μ œ μ½”λ“œκ°€ 호좜되기 μ „κΉŒμ§€ 문제λ₯Ό λ°œκ²¬ν•  수 μ—†λ‹€λŠ” 것이닀.

 

κ·Έλ ‡λ‹€λ©΄ μƒμ„±μž μ£Όμž…μ„ μ‚¬μš©ν•œ κ²½μš°μ—λŠ” μ–΄λ–»κ²Œ 될까?

@Service
public class ProductService {

    private final ReviewService reviewService;

    public ReviewService(ReviewService reviewService) {
        this.reviewService = reviewService;
    }
}
@Service
public class ReviewService {

    private final ProductService productService;

    public ProductService(ProductService productService) {
        this.productService = productService;
    }
}

μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹€ν–‰ μ‹œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ ꡬ동 μ‹œμ (객체의 생성 지점)에 BeanCurrentlyInCreationException이 λ°œμƒν•˜μ—¬ 였λ₯˜λ₯Ό 사전에 μ•Œ 수 μžˆλ‹€.

Description:
The dependencies of some of the beans in the application context form a cycle:
β”Œβ”€β”€β”€β”€β”€β”
|  reviewService defined in file [~~~\ReviewService.class]
↑     ↓
|  productService defined in file [~~~\ProductService.class]
β””β”€β”€β”€β”€β”€β”˜

 

πŸ€” μ™œ 이런 차이가 λ‚ κΉŒ?

μ΄λŸ¬ν•œ μ‹€ν–‰ 결과의 μ°¨μ΄λŠ” μƒμ„±μž μ£Όμž…μ€ Bean을 μ£Όμž…ν•˜λŠ” μˆœμ„œκ°€ ν•„λ“œ μ£Όμž…κ³Ό μˆ˜μ •μž μ£Όμž…κ³ΌλŠ” λ‹€λ₯΄κΈ° λ•Œλ¬Έμ΄λ‹€.

 

@Autowiredλ₯Ό μ΄μš©ν•œ ν•„λ“œ μ£Όμž…μ„ ν–ˆμ„ λ•Œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ ꡬ동 μ‹œμ μ— μ—λŸ¬κ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ” μ΄μœ λŠ” 빈의 생성과 쑰립(@Autowired) μ‹œμ μ΄ λΆ„λ¦¬λ˜μ–΄ 있기 λ•Œλ¬Έμ΄λ‹€. μƒμ„±μž μ£Όμž…μ€ 객체의 생성과 쑰립(μ˜μ‘΄κ΄€κ³„ μ£Όμž…)이 λ™μ‹œμ— 싀행돼 μœ„μ™€ 같은 μ—λŸ¬λ₯Ό 사전에 μž‘μ„ 수 μžˆλ‹€. ν•˜μ§€λ§Œ @AutowiredλŠ” λͺ¨λ“  Bean 생성이 μ™„λ£Œλœ 후에 쑰립(μ˜μ‘΄κ΄€κ³„ μ£Όμž…)이 처리돼 호좜이 되고 λ‚˜μ„œμ•Ό μˆœν™˜ 이슈λ₯Ό 확인할 수 μžˆλŠ” 것이닀.

 

참고둜 Spring Boot 2.6 λΆ€ν„°λŠ” 기본적으둜 Bean κ°„μ˜ μˆœν™˜ μ°Έμ‘°κ°€ κΈˆμ§€λ˜λ„λ‘ λ³€κ²½λ˜μ—ˆλ‹€.

 

🌱 ν…ŒμŠ€νŠΈμ— 용이

μƒμ„±μž μ£Όμž… μ‚¬μš© μ‹œ ν…ŒμŠ€νŠΈ μ½”λ“œλ₯Ό 더 νŽΈλ¦¬ν•˜κ²Œ μž‘μ„±ν•  수 μžˆλ‹€.

ν…ŒμŠ€νŠΈκ°€ νŠΉμ • ν”„λ ˆμž„μ›Œν¬μ— μ˜μ‘΄ν•˜λŠ” 것은 ν…ŒμŠ€νŠΈ 격리가 μ–΄λ ΅κ³  μœ μ—°μ„±μ΄ κ°μ†Œν•΄ μ’‹μ§€ μ•Šλ‹€. λ”°λΌμ„œ λ…λ¦½μ μœΌλ‘œ μΈμŠ€ν„΄μŠ€ν™”κ°€ κ°€λŠ₯ν•œ POJO(Plain Old Java Object)둜 μž‘μ„±ν•˜λŠ” 것이 쒋은데, μƒμ„±μž μ£Όμž…μ΄ μ•„λ‹Œ λ‹€λ₯Έ μ£Όμž…μœΌλ‘œ μž‘μ„±λœ μ½”λ“œλŠ” 순수 μžλ°” μ½”λ“œλ‘œ λ‹¨μœ„ ν…ŒμŠ€νŠΈλ₯Ό μž‘μ„±ν•˜λŠ” 것이 μ–΄λ ΅λ‹€.

 

@Service
public class ProductService {

    @Autowired
    private ProductRepository productRepository;

    public void createProduct(String name) {
        productRepository.create(name);
    }
}

예λ₯Όλ“€μ–΄ μœ„μ™€ 같은 ν•„λ“œ μ£Όμž… 방식 μ½”λ“œμ— λŒ€ν•΄ 순수 μžλ°” ν…ŒμŠ€νŠΈ μ½”λ“œλ₯Ό μž‘μ„±ν•˜λ©΄ λ‹€μŒκ³Ό 같이 μž‘μ„±ν•  수 μžˆλ‹€.

public class ProductServiceTest {

    @Test
    public void createProductTest() {
        ProductService productService = new ProductService();
        productService.createProduct("μƒν’ˆ1");
    }
}

μœ„μ˜ ν…ŒμŠ€νŠΈ μ½”λ“œλŠ” Spring μœ„μ—μ„œ λ™μž‘ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ μ˜μ‘΄κ΄€κ³„ μ£Όμž…μ΄ λ˜μ§€ μ•ŠλŠ”λ‹€. λ”°λΌμ„œ postRepositoryκ°€ null이 λ˜μ–΄ findById 호좜 μ‹œ NPEκ°€ λ°œμƒν•  것이닀. 이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ Setter μ‚¬μš© μ‹œ λ³€κ²½ κ°€λŠ₯성을 μ—΄μ–΄λ‘κ²Œ λ˜λŠ” 단점을 κ°–κ²Œ λœλ‹€.

λ°˜λŒ€λ‘œ ν…ŒμŠ€νŠΈ μ½”λ“œμ—μ„œ @Autowiredλ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄ μŠ€ν”„λ§μ„ μ‚¬μš©ν•˜λ©΄ λ‹¨μœ„ ν…ŒμŠ€νŠΈκ°€ 아닐 뿐 μ•„λ‹ˆλΌ, μ»΄ν¬λ„ŒνŠΈλ“€μ„ λ“±λ‘ν•˜κ³  μ΄ˆκΈ°ν™”ν•˜λŠ” μ‹œκ°„ λ•Œλ¬Έμ— ν…ŒμŠ€νŠΈ λΉ„μš©μ΄ μ¦κ°€ν•˜κ²Œ λœλ‹€.

λ°˜λ©΄μ— μƒμ„±μž μ£Όμž… μ‚¬μš© μ‹œ 컴파일 μ‹œμ μ— 객체λ₯Ό μ£Όμž…λ°›μ•„ ν…ŒμŠ€νŠΈ μ½”λ“œλ₯Ό μž‘μ„±ν•  수 있으며, μ£Όμž…ν•˜λŠ” 객체가 λˆ„λ½λœ 경우 컴파일 μ‹œμ μ— 였λ₯˜λ₯Ό λ°œκ²¬ν•  수 μžˆλ‹€.

 

🌱 μŠ€ν”„λ§μ— 독립적인 μ½”λ“œ μž‘μ„±

ν•„λ“œ μ£Όμž… μ‚¬μš© μ‹œ @Autowiredλ₯Ό μ΄μš©ν•΄μ•Ό ν•˜λŠ”λ°, 이것은 μŠ€ν”„λ§μ΄ μ œκ³΅ν•˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜μ΄λ‹€.

κ·ΈλŸ¬λ―€λ‘œ @Autowiredλ₯Ό μ‚¬μš©ν•˜λ©΄ ProductService에 μŠ€ν”„λ§ μ˜μ‘΄μ„±μ΄ 생긴닀.

import org.springframework.beans.factory.annotation.Autowired;
// μŠ€ν”„λ§ μ˜μ‘΄μ„±μ΄ ProductService에 importλ˜μ–΄ μ½”λ“œλ‘œ λ°•νž˜

@Service
public class ProductService {

    @Autowired
    private ProductRepository productRepository;

}

μ‚¬μš©ν•˜λŠ” ν”„λ ˆμž„μ›Œν¬λŠ” μ–Έμ œ λ°”λ€”μ§€ λͺ¨λ₯΄κ³ , ν”„λ ˆμž„μ›Œν¬λŠ” λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ μž‘μ„±ν•˜λŠ” μ„œλΉ„μŠ€ κ³„μΈ΅μ—μ„œ μ•Œμ•„μ•Ό ν•  λŒ€μƒμ΄ μ•„λ‹ˆλ‹€.

μ΄λŠ” ν•„μš”ν•œ μžλ°” νŒŒμΌμ„ importν•΄μ•Όν•˜λŠ” 정적 언어인 μžλ°”μ˜ ν•œκ³„μ΄κΈ°λ„ ν•˜λ‚˜, κ°€λŠ₯ν•œ μŠ€ν”„λ§ 없이 μ½”λ“œκ°€ μž‘μ„±λ˜λ©΄ λ”μš± μœ μ—°ν•œ μ½”λ“œ 확보가 κ°€λŠ₯ν•˜λ‹€.

 

🌱 객체 λΆˆλ³€μ„±(Immutability) 확보

μ‹€μ œ κ°œλ°œμ„ ν•˜λ‹€λ³΄λ©΄ 의쑴 κ΄€κ³„μ˜ 변경이 ν•„μš”ν•œ 상황은 κ±°μ˜μ—†λ‹€. ν•˜μ§€λ§Œ μˆ˜μ •μž μ£Όμž…μ΄λ‚˜ 일반 λ©”μ„œλ“œ μ£Όμž…μ„ μ΄μš©ν•˜λ©΄ λΆˆν•„μš”ν•˜κ²Œ μˆ˜μ •μ˜ κ°€λŠ₯성을 열어두어 μœ μ§€λ³΄μˆ˜μ„±μ„ λ–¨μ–΄λœ¨λ¦°λ‹€. κ·ΈλŸ¬λ―€λ‘œ μƒμ„±μž μ£Όμž…μ„ 톡해 변경이 κ°€λŠ₯성을 λ°°μ œν•˜κ³  λΆˆλ³€μ„±μ„ 보μž₯ν•˜λŠ”κ²ƒμ΄ μ’‹λ‹€.

μ΄λŠ” 였λ₯˜λ₯Ό 사전에 λ°©μ§€ν•  수 μžˆλŠ” μž₯점을 가지기도 ν•œλ‹€.

 

@Service
public class ProductService {

    @Autowired
    private ProductRepository productRepository;
    
    public void someMethod() {
        productRepository = null;
        productRepository.call();
    }
}

ν•„λ“œ μ£Όμž…μ„ μ‚¬μš©ν•œ μ½”λ“œλŠ” final ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•  수 μ—†λ‹€. λ”°λΌμ„œ λŸ°νƒ€μž„ μ‹œμ μ— 변경될 수 μžˆλ‹€.

μœ„ μ½”λ“œμ—μ„œλŠ” null을 μ°Έμ‘°ν•˜λ„λ‘ λ³€κ²½ν–ˆκΈ° λ•Œλ¬Έμ— NullPointerException이 λ°œμƒν•  것이닀.

ν•˜μ§€λ§Œ μƒμ„±μž μ£Όμž…μ„ μ‚¬μš©ν•œλ‹€λ©΄ 이와 같은 상황을 컴파일 μ‹œμ μ— λ°©μ§€ν•  수 μžˆλ‹€.

@Service
public class ProductService {
    private final ProductRepository productRepository;

    public ProductRepository(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }
    
    public void someMethod() {
        // final λ³€μˆ˜μ— 값을 μž¬ν• λ‹Ή ν•  수 μ—†μŒ
        productRepository = null;
    }
}

 

🌱 final ν‚€μ›Œλ“œ μž‘μ„± 및 Lombok과의 κ²°ν•©

μƒμ„±μž μ£Όμž…μ„ μ‚¬μš©ν•˜λ©΄ ν•„λ“œ 객체에 final ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•  수 있으며 컴파일 μ‹œμ μ— λˆ„λ½λœ μ˜μ‘΄μ„±μ„ 확인할 수 μžˆλ‹€.

λ°˜λ©΄μ— λ‹€λ₯Έ μ£Όμž… 방법듀은 객체의 생성(μƒμ„±μž 호좜) 이후에 ν˜ΈμΆœλ˜λ―€λ‘œ final ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•  수 μ—†λ‹€.

 

final ν‚€μ›Œλ“œλ‘œ ν•„λ“œλ₯Ό λͺ…μ‹œμ μœΌλ‘œ μ„ μ–Έν•˜λ©΄ μ½”λ“œμ˜ 가독성과 μ•ˆμ •μ„±μ„ 높일 수 있으며, λ‹€λ₯Έ κ°œλ°œμžλ“€μ΄ ν•΄λ‹Ή ν•„λ“œκ°€ λΆˆλ³€μ΄λΌλŠ” 것을 μ•Œ 수 μžˆμ–΄ μ½”λ“œμ˜ 이해λ₯Ό λ„μšΈ 수 μžˆλŠ” μž₯점이 μžˆλ‹€.


λ˜ν•œ final ν‚€μ›Œλ“œλ₯Ό 뢙이면 Lombokκ³Ό κ²°ν•©λ˜μ–΄ μ½”λ“œλ₯Ό κ°„κ²°ν•˜κ²Œ μž‘μ„±ν•  수 μžˆλ‹€. Lombokμ—λŠ” final λ³€μˆ˜λ₯Ό μœ„ν•œ μƒμ„±μžλ₯Ό λŒ€μ‹  μƒμ„±ν•΄μ£ΌλŠ” @RequiredArgsConstructorκ°€ μžˆλŠ”λ° μƒμ„±μž μ£Όμž… μ½”λ“œλ₯Ό Lombokκ³Ό κ²°ν•©μ‹œν‚€λ©΄ λ‹€μŒκ³Ό 같이 κ°„νŽΈν•˜κ²Œ μž‘μ„±ν•  수 μžˆλ‹€.

@Service
@RequiredArgsConstructor
public class ProductService {

    private final ProductRepository productRepository;
    private final UserRepository userRepository;

	public void createProduct(String name) {
        productRepository.create(name);
    }
}

 

 

 

 

 

 

[Spring] λ‹€μ–‘ν•œ μ˜μ‘΄μ„± μ£Όμž… 방법과 μƒμ„±μž μ£Όμž…μ„ μ‚¬μš©ν•΄μ•Ό ν•˜λŠ” 이유 - (2/2)

Spring ν”„λ ˆμž„μ›Œν¬μ˜ 핡심 기술 쀑 ν•˜λ‚˜κ°€ λ°”λ‘œ DI(Dependency Injection, μ˜μ‘΄μ„± μ£Όμž…)이닀. Spring ν”„λ ˆμž„μ›Œν¬μ™€ 같은 DI ν”„λ ˆμž„μ›Œν¬λ₯Ό μ΄μš©ν•˜λ©΄ λ‹€μ–‘ν•œ μ˜μ‘΄μ„± μ£Όμž…μ„ μ΄μš©ν•˜λŠ” 방법이 μžˆλŠ”λ°, 각각의 λ°©

mangkyu.tistory.com

 

μƒμ„±μž μ£Όμž…μ„ @Autowiredλ₯Ό μ‚¬μš©ν•˜λŠ” ν•„λ“œ μ£Όμž…λ³΄λ‹€ ꢌμž₯ν•˜λŠ” ν•˜λŠ” 이유

@Autowiredλ₯Ό μ‚¬μš©ν•˜λŠ” μ˜μ‘΄μ„± μ£Όμž…λ³΄λ‹€ μƒμ„±μž μ£Όμž…(Constructor Injection)을 더 ꢌμž₯ν•˜λŠ” μ΄μœ λŠ” λ¬΄μ—‡μΌκΉŒ?

madplay.github.io

 

의쑴 관계 μ£Όμž…(DI) - spring

예λ₯Όλ“€μ–΄, μ½”λ“œμ—μ„œ 자주 μ‚¬μš©ν•˜λŠ” 메인 λ°μ΄ν„°λ² μ΄μŠ€μ˜ 컀λ„₯μ…˜μ„ νšλ“ν•˜λŠ” 빈이 있고, μ½”λ“œμ—μ„œ νŠΉλ³„ν•œ κΈ°λŠ₯으둜 가끔 μ‚¬μš©ν•˜λŠ” μ„œλΈŒ λ°μ΄ν„°λ² μ΄μŠ€μ˜ 컀λ„₯μ…˜μ„ νšλ“ν•˜λŠ” μŠ€ν”„λ§ 빈이 μžˆλŠ” κ²½

dahye-jeong.gitbook.io

 

Field injection is not recommended – Spring IOC - Marc Nuri

When running a static code analysis tool or inspecting/analyzing your code from your IDE, you may have encountered the following warning regarding your @Autowired fields: Field injection is not recommended. This post shows the alternatives to field injecti

blog.marcnuri.com

 

 

πŸ’‰Dependency Injection in Spring: Constructor, Property, or Setter? Which one should I choose?

Dependency injection is a programming technique in which objects are created with all the dependencies they need to function properly…

medium.com

 

[Spring] λ‹€μ–‘ν•œ μ˜μ‘΄μ„± μ£Όμž… 방법과 μƒμ„±μž μ£Όμž…μ„ μ‚¬μš©ν•΄μ•Ό ν•˜λŠ” 이유 - (2/2)

Spring ν”„λ ˆμž„μ›Œν¬μ˜ 핡심 기술 쀑 ν•˜λ‚˜κ°€ λ°”λ‘œ DI(Dependency Injection, μ˜μ‘΄μ„± μ£Όμž…)이닀. Spring ν”„λ ˆμž„μ›Œν¬μ™€ 같은 DI ν”„λ ˆμž„μ›Œν¬λ₯Ό μ΄μš©ν•˜λ©΄ λ‹€μ–‘ν•œ μ˜μ‘΄μ„± μ£Όμž…μ„ μ΄μš©ν•˜λŠ” 방법이 μžˆλŠ”λ°, 각각의 λ°©

mangkyu.tistory.com