1. Circular Dependency (์ํ ์์กด์ฑ)
- ๋ ๊ฐ ์ด์์ ๊ฐ์ฒด ๊ฐ์ ์๋ก๊ฐ ์๋ก์ ๋ํด ์์กดํ๋ ์ํฉ
- A -> B๋ฅผ ์ฐธ์กฐํ๋ ๋์์ B -> A๋ฅผ ์ฐธ์กฐ
- BeanCurrentlyInCreationException ์์ธ๊ฐ ๋ฐ์ํ ์ ์๋ค.
Circular Dependency์ ๋ฌธ์ ์
@Configuration
class CircularConfig{
@Bean
public A a (B b) {
return new A(b);
}
@Bean
public B b(A a) {
return new B(a);
}
}
- ์ด๋ ๋น์ ๋จผ์ ์์ฑํ๊ณ ์ฃผ์ ํด์ผ ํ๋์ง ํ๋จํ๊ธฐ ์ด๋ ต๋ค. -> BeanCurrentlyInCreationException ๋ฐ์
- ์์กด์ฑ ์ฃผ์ ์ด ์ํ์ ์ผ๋ก ๊ณ์๋๋ ๊ฒฝ์ฐ, ๋ฌดํ ๋ฃจํ๊ฐ ๋ฐ์ํ ์๋ ์๋ค.
ํด๋น ๋ฌธ์ ์ ์ ํด๊ฒฐํ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ ํ๋จ ๋ธ๋ก๊ทธ ์ฐธ๊ณ !
https://www.baeldung.com/circular-dependencies-in-spring
2. Component Scan
์คํ๋ง์ด ์ง์ ํด๋์ค๋ฅผ ๊ฒ์ํด์ ๋น์ผ๋ก ๋ฑ๋กํด ์ฃผ๋ ๊ธฐ๋ฅ
=> ์ค์ ํด๋์ค์ ๋น์ผ๋ก ์ง์ ๋ฑ๋กํ์ง ์์๋ ์ํ๋ ํด๋์ค๋ฅผ ๋น์ผ๋ก ๋ฑ๋กํ ์ ์๋ค.
@ComponentScan
์ปดํฌ๋ํธ ์ค์บ๋์ ์ํํ๋ค.
๐ ์ปดํฌ๋ํธ ์ค์บ๋
- ํ์ฌ ์คํ ์ค์ธ ์ค์ ํด๋์ค๊ฐ ์ํ ํจํค์ง์ ๊ทธ ํ์ ํจํค์ง์์ ์ปดํฌ๋ํธ๋ค์ ์ค์บ๋ํ๋ค.
- ์ปดํฌ๋ํธ๋ @Component, @Controller, @Service, @Repository ๋ฑ์ ์คํ๋ง ๊ด๋ จ ์ ๋
ธํ
์ด์
์ด ๋ถ์ฌ๋ ํด๋์ค๋ฅผ ์๋ฏธํ๋ค.
๐ ์๋ ๋น ๋ฑ๋ก
- ์ปดํฌ๋ํธ ์ค์บ๋์ ํตํด ์ฐพ์์ง ํด๋์ค๋ค์ ์๋์ผ๋ก ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋ก๋๋ค.
- ๊ฐ๋ฐ์๋ ๋น ๋ฑ๋ก์ ๋ํ ๋ช
์์ ์ธ ์ค์ ์ ์ค์ผ ์ ์๋ค.
๐ ํจํค์ง ๋ฐ ํํฐ๋ง ์ค์
- ์ค์บ๋ํ ํจํค์ง๋ฅผ ์ง์ ํ ์ ์์ผ๋ฉฐ, includeFilters์ excludeFilters๋ฅผ ํตํด ํน์ ์กฐ๊ฑด์ ๋ฐ๋ผ ์ค์บ๋ํ ํด๋์ค๋ฅผ ํํฐ๋งํ ์๋ ์๋ค.
- ์ค์บ๋ ๋ฒ์๋ฅผ ์ธ๋ฐํ๊ฒ ์ ์ดํ ์ ์๋ค.
๐ ๋ค์ค @ComponentScan
- ์ฌ๋ฌ ๊ฐ์ @ComponentScan ์ ๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ๋ค๋ฅธ ํจํค์ง๋ฅผ ๋์์ผ๋ก ์ค์บ๋ํ ์ ์๋ค.
- ์ฌ๋ฌ ํจํค์ง์ ๊ฑธ์ณ ์๋ ์ปดํฌ๋ํธ๋ค์ ํ ๋ฒ์ ๋ฑ๋กํ ์ ์์ต๋๋ค.
๐ค ์คํ๋ง์ ์๋์ผ๋ก ๋ฑ๋ก๋ Bean์ ์ด๋ป๊ฒ ์ฐพ์๊น?
Stereotype ์ ๋ ธํ ์ด์ ์ ์ด์ฉํด์ ์ฐพ๋๋ค.
Stereotype
- ์คํ๋ง ํ๋ ์์ํฌ์์ ์ ๊ณตํ๋ ์ ๋ ธํ ์ด์ ๋ค์ ๊ทธ๋ฃน์ผ๋ก, ํน์ ํ ์๋ฏธ์ ์ญํ ์ ๊ฐ์ง ์ ๋ ธํ ์ด์ ๋ค์ ์ง์นญํ๋ค.
- ์ปดํฌ๋ํธ ์ค์บ(ComponentScan)๊ณผ ํจ๊ป ์ฌ์ฉ๋์ด ํน์ ์ ๋
ธํ
์ด์
์ด ๋ถ์ ํด๋์ค๋ค์ ์ค์บํ์ฌ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋กํ๋ ์์
์ ์ํํ๋ค.
๐ @Component
ํด๋น ํด๋์ค๋ฅผ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋กํ๋ค.
๐ข @Bean์ @Component์ ์ฐจ์ด์
@Component
- ํด๋์ค ์๋จ์ ์ ์ผ๋ฉฐ, default๋ก ํด๋์ค ์ด๋ฆ์ด Bean์ ์ด๋ฆ์ด ๋๋ค.
- ์คํ๋ง์์ @ComponentScan์ ์ฌ์ฉํด์ ์๋์ผ๋ก ์ฐพ์์ฃผ๊ณ ๊ด๋ฆฌํด ์ค๋ค.
@Bean
- @Configuration์ผ๋ก ์ ์ธ๋ ํด๋์ค ๋ด์ ์๋ ๋ฉ์๋๋ฅผ ์ ์ํ ๋ ์ฌ์ฉํ๋ค.
- ์ด ๋ฉ์๋๊ฐ ๋ฐํํ๋ ๊ฐ์ฒด๊ฐ Bean์ด ๋๋ฉฐ, default๋ก ๋ฉ์๋ ์ด๋ฆ์ด Bean์ ์ด๋ฆ์ด ๋๋ค.
๐ @Configuration
- ํ ๊ฐ ์ด์์ @Bean ์ ๋ ธํ ์ด์ ์ผ๋ก ์ ์ํ bean ๋ค์ ์์ฑํ๋ ค ํ ๋ ํด๋์ค์ ์ ์ํ๋ ์ด๋ ธํ ์ด์
- ์ค์ ํด๋์ค๋ฅผ ๋ํ๋ด๋ ์ ๋ ธํ ์ด์ ์ผ๋ก ์คํ๋ง ๋น์ ์ ์ํ๊ณ ์ค์ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ค.
๐ @Repository
- ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ํธ์์ฉ์ ๋ด๋นํ๋ ๋ฆฌํฌ์งํ ๋ฆฌ(๋ฐ์ดํฐ ์ ๊ทผ ๊ณ์ธต) ํด๋์ค๋ฅผ ๋ํ๋ด๋ ์ ๋ ธํ ์ด์
- ๋ฐ์ดํฐ๋ฒ ์ด์ค CRUD ์์ ์ด๋ ๋ฐ์ดํฐ ์กฐ์๊ณผ ๊ด๋ จ๋ ๋ก์ง์ ๊ตฌํํ๋ ๋ฐ ์ฌ์ฉ๋๋ค.
๐ @Service
- ๋น์ฆ๋์ค ๋ก์ง์ ์ฒ๋ฆฌํ๋ ์๋น์ค ํด๋์ค๋ฅผ ๋ํ๋ด๋ ์ ๋ ธํ ์ด์
- ์ฃผ๋ก ์ปจํธ๋กค๋ฌ์ ๋ฆฌํฌ์งํ ๋ฆฌ ์ฌ์ด์์ ๋ฐ์ดํฐ ์กฐ์์ด๋ ๋น์ฆ๋์ค ๊ท์น์ ๊ตฌํํ๋ ๋ฐ ์ฌ์ฉ๋๋ค.
๐ @Controller
- ์น ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ปจํธ๋กค๋ฌ ์ญํ ์ ์ํํ๋ ํด๋์ค๋ฅผ ๋ํ๋ด๋ ์ ๋ ธํ ์ด์
- MVC ์ํคํ ์ฒ์์ ์ฌ์ฉ๋๋ฉฐ, ํด๋ผ์ด์ธํธ์ ์์ฒญ์ ์ฒ๋ฆฌํ๊ณ ์ ์ ํ ์๋ต์ ๋ฐํํ๋ ์ญํ ์ ๋ด๋นํฉ๋๋ค
3. Component Scan ์ค์ต
Repository ๊ตฌํ์ฒด ๋ง๋ค๊ธฐ
@Repository
public class MemoryVoucherRepository implements VoucherRepository {
private final Map<UUID, Voucher> storage = new ConcurrentHashMap<>();
@Override
public Voucher insert(Voucher voucher) {
storage.put(voucher.getVoucherId(), voucher);
return voucher;
}
}
@Repository ์ ๋ ธํ ์ด์ ์ ํตํด์ VoucherRespository์ ๊ตฌํ์ฒด์ธ MemoryVoucherRepository๋ฅผ ์ค์บํ ์ ์๋๋ก ํ๋ค.
๐ค interface์ธ VoucherRepository์๋ ์ ๋ถ์ฌ๋ ๋๋?
๋ถ์ฌ๋ ๋๊ณ ์ ๋ถ์ฌ๋ ๋์ง๋ง ๋ณดํต์ ๊ฒฝ์ฐ ๊ตฌํ์ฒด์๋ง ๋ถ์ธ๋ค.
Spring์ @Repository ์ ๋ ธํ ์ด์ ์ด ๋ถ์ ํด๋์ค๋ฅผ ์ค์บํ์ฌ Repository ์ธํฐํ์ด์ค์ ๋งคํํ๋ ๋ฐฉ์์ผ๋ก ๋์ํ๋ค.
=> MemoryVoucherRepository๋ฅผ VoucherRepository ์ธํฐํ์ด์ค์ ๋น์ผ๋ก ๋ฑ๋ก
+) interface์ธ VoucherRepository์๋ง @Repository ์ ๋ ธํ ์ด์ ์ ๋ถ์ด๋ฉด ๊ตฌํ์ฒด๋ฅผ Bean์ผ๋ก ๋ฑ๋กํ๊ฑฐ๋ ๊ด๋ฆฌํ ์ ์๋ค.
๐ก ConcurrentHashmap์ด๋?
Hashtable ํด๋์ค์ ๋จ์ ์ ๋ณด์ํ๋ฉด์ Multi-Thread ํ๊ฒฝ์์ ์ฌ์ฉํ ์ ์๋๋ก ๋์จ ํด๋์ค
- Thread-Safe ํ๋ค
- ์ด๋ค Entry๋ฅผ ์กฐ์ํ๋ ๊ฒฝ์ฐ์ ํด๋น Entry์ ๋ํด์๋ง ๋ฝ์ ๊ฑด๋ค.
- HashTable๋ณด๋ค ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ์๋๊ฐ ๋น ๋ฅด๋ค.
=> Entry ์์ดํ ๋ณ๋ก ๋ฝ์ ๊ฑธ์ด ๋ฉํฐ ์ค๋ ๋ ํ๊ฒฝ์์์ ์ฑ๋ฅ์ ํฅ์์ํจ๋ค.
๋์์๋ฆฌ๊ฐ ๊ถ๊ธํ๋ค๋ฉด ์ถ๊ฐ๋ก ๋ณด๋ฉด ์ข์ ๋ฏ!
[Java] ConcurrentHashMap๋ ์ด๋ป๊ฒ Thread-safe ํ๊ฐ?
Service์์ Repository ์์กด์ฑ ์ฃผ์ ๋ฐ๊ธฐ
@Service
public class VoucherService {
private final VoucherRepository voucherRepository;
public VoucherService(VoucherRepository voucherRepository) {
this.voucherRepository = voucherRepository;
}
}
VoucherService์์ ์์ฑ์๋ฅผ ํตํ ์์กด์ฑ ์ฃผ์ ์ ํตํด ์คํ๋ง์ ์๋์ผ๋ก MemoryVoucherRepository ๋น์ ์ฃผ์ ํ์ฌ ์ฌ์ฉํ๋ค.
+) MemoryVoucherRepository ํด๋์ค๊ฐ VoucherRepository ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ณ ์์ผ๋ฉฐ @Repository ์ ๋ ธํ ์ด์ ์ด ๋ถ์ด์๊ธฐ ๋๋ฌธ์, ํด๋น ํด๋์ค์ ์ธ์คํด์ค๊ฐ VoucherRepository ํ์ ์ ๋น์ผ๋ก ๋ฑ๋ก๋์ด ์์ผ๋ฉด ์ฃผ์ ๋๋ค.
๐คVoucherRepository์ ๊ตฌํ์ฒด๊ฐ ์ฌ๋ฌ ๊ฐ์ธ ๊ฒฝ์ฐ์๋ ์ด๋ป๊ฒ ๋์ํ ๊น?
1. @Qualifier์ ์ฌ์ฉํ ๋ช ์์ ์ธ ๋น ์ฃผ์
@Service
public class VoucherService {
private final VoucherRepository voucherRepository;
@Autowired
public VoucherService(@Qualifier("memoryVoucherRepository") VoucherRepository voucherRepository) {
this.voucherRepository = voucherRepository;
}
// ...
}
VoucherService ํด๋์ค์ ์์ฑ์์ @Qualifier ์ ๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ "memoryVoucherRepository"๋ผ๋ ์ด๋ฆ์ ๋น์ ์ฃผ์ ํ๋๋ก ๋ช ์์ ์ผ๋ก ์ง์ ํ๊ณ ์๋ค. ์คํ๋ง์ ํด๋น ์ด๋ฆ์ ๊ฐ์ง ๋น์ ์ฐพ์์ ์ฃผ์ ํ๋ค.
2. @Primary๋ฅผ ์ฌ์ฉํ ์ฐ์ ์ ์ธ ๋น ์ฃผ์
@Repository
@Primary
public class MemoryVoucherRepository implements VoucherRepository {
// ...
}
@Primary ์ ๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ MemoryVoucherRepository ํด๋์ค๋ฅผ ์ฃผ ์ฉ๋๋ก ์ฌ์ฉํ๋ ๊ธฐ๋ณธ ๋น์ผ๋ก ์ง์ ํ๊ณ ์๋ค.
VoucherService ํด๋์ค์์ VoucherRepository๋ฅผ ์ฃผ์
๋ฐ์ ๋ ๋ช
์์ ์ผ๋ก ์ด๋ค ๋น์ ์ฃผ์
ํ ์ง ์ง์ ํ์ง ์์๋ค๋ฉด, ์คํ๋ง์ @Primary ์ ๋
ธํ
์ด์
์ด ๋ถ์ MemoryVoucherRepository ๋น์ ์ฐ์ ์ ์ผ๋ก ์ฃผ์
ํ๋ค.
+) ๋ฐ๋์ ํ๋์ ๋น์๋ง ์ ์ฉํด์ผ ํ๋ค.
๐ก@Qualifier์ @Primary์ ์ฐ์ ์์
1. @Qualifier๋ก ๋ช ์ํ ๋น์ด ์ฐ์ ์ ์ผ๋ก ์ฃผ์ ๋๋ค.
2. @Qualifier๋ก ๋ช ์ํ ๋น์ด ์๋ ๊ฒฝ์ฐ, @Primary ์ ๋ ธํ ์ด์ ์ด ๋ถ์ ๋น์ด ์ฃผ์ ๋๋ค.
3. @Qualifier๋ก ๋ช ์ํ ๋น์ด ์๊ณ , @Primary ์ ๋ ธํ ์ด์ ์ด ๋ถ์ ๋น๋ ์๋ ๊ฒฝ์ฐ์๋ NoSuchBeanDefinitionException ์์ธ๊ฐ ๋ฐ์ํฉ๋๋ค.
ComponentScan์ ํน์ ํจํค์ง ์ง์ ํ๊ธฐ
1. @ComponentScan(basePackages = {})
ํจํค์ง์ ์ด๋ฆ์ ์ง์ ์ง์ ํ๋ ๋ฐฉ๋ฒ
๋ฌธ์์ด ๋ฐฐ์ด์ ์ ๋ฌํ์ฌ ์ค์บํ ํจํค์ง๋ฅผ ๋ช ์ํ๋ค.
@ComponentScan(basePackages = {"org.prgms.kdt.springorder.order", "org.prgms.kdt.springorder.voucher"})
์ค์ ํ์ผ๊ณผ ๊ฐ์ ํจํค์ง์ ์์ด๋ ํด๋น ๋ฐฐ์ด์ ํฌํจ๋์ง ์์ผ๋ฉด ์ค์บํ์ง ์๋๋ค.
2. @ComponentScan(basePackageClasses = {})
ํด๋์ค๋ฅผ ๊ธฐ์ค์ผ๋ก ํจํค์ง๋ฅผ ์ง์ ํ๋ ๋ฐฉ๋ฒ
ํด๋์ค ๋ฐฐ์ด์ ์ ๋ฌํ์ฌ, ํด๋น ํด๋์ค๊ฐ ์กด์ฌํ๋ ํจํค์ง๊ฐ ์ค์บ ๋์์ด ๋๋ค.
@ComponentScan(basePackageClasses = {Order.class, Voucher.class})
Order.class์ Voucher.class๊ฐ ์๋ ํจํค์ง๋ง ์ค์บํ๋ค.
๐กexcludeFilters, includeFilters
excludeFilters
์ค์บ ๋์์์ ์ ์ธํ ํํฐ๋ฅผ ์ง์ ํ๋ค.
์ฆ, ํด๋น ํํฐ์ ์กฐ๊ฑด์ ๋ง์กฑํ๋ ์ปดํฌ๋ํธ๋ ์ค์บ ๋์์์ ์ ์ธ๋ฉ๋๋ค.
includeFilters
์ค์บ ๋์์ ํฌํจํ ํํฐ๋ฅผ ์ง์ ํ๋ค.
์ฆ, ํด๋น ํํฐ์ ์กฐ๊ฑด์ ๋ง์กฑํ๋ ์ปดํฌ๋ํธ๋ง ์ค์บ ๋์์ผ๋ก ํฌํจ๋๋ค.
๐ FilterType ์ข ๋ฅ
FilterType.ANNOTATION: ํน์ ์ ๋ ธํ ์ด์ ์ด ์ ์ฉ๋ ํด๋์ค๋ฅผ ๋์์ผ๋ก ํ๋ค.
FilterType.ASSIGNABLE_TYPE: ํน์ ํด๋์ค๋ ์ธํฐํ์ด์ค๋ฅผ ์์ํ๊ฑฐ๋ ๊ตฌํํ ํด๋์ค๋ฅผ ๋์์ผ๋ก ํ๋ค.
FilterType.REGEX: ์ ๊ท์ ํจํด๊ณผ ์ผ์นํ๋ ํด๋์ค ์ด๋ฆ์ ๊ฐ์ง๊ณ ์๋ ์ปดํฌ๋ํธ๋ฅผ ๋์์ผ๋ก ํ๋ค.
FilterType.ASPECTJ: AspectJ ํจํด๊ณผ ์ผ์นํ๋ ํด๋์ค๋ฅผ ๋์์ผ๋ก ํ๋ค.
FilterType.CUSTOM: ์ปค์คํ ํํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์ค์บ ๋์์ ์ ์ดํ๋ค. ์ปค์คํ ํํฐ๋ TypeFilter ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํด์ผ ํ๋ฉฐ, match() ๋ฉ์๋๋ฅผ ํตํด ์กฐ๊ฑด์ ์ ์ํ๋ค.
4. Autowired
SpringBoot 1-2์์ ์ ๊น ๋ค๋ค๋ DI ์ข ๋ฅ๋ค์ด๋ค.
์์๋ฅผ ๋ค์ด ์ข ๋ ์์ธํ ์ดํด๋ณด์.
DI ์ข ๋ฅ
๐ ์์ฑ์ ์ฃผ์ (Constructor Injection)
๊ฐ์ฒด์ ์์ฑ์๋ฅผ ํตํด ์์กด์ฑ์ ์ฃผ์ ํ๋ ๋ฐฉ์
๊ฐ์ฒด์ ์์ฑ ์์ ์ ํ์ํ ์์กด์ฑ์ ์ธ๋ถ์์ ์ ๋ฌ๋ฐ์ ์ฌ์ฉํ๋ค.
private final VoucherRepository voucherRepository;
public VoucherService(VoucherRepository voucherRepository) {
this.voucherRepository = voucherRepository;
}
์์ฑ์๊ฐ ํ๋์ธ ๊ฒฝ์ฐ์๋ง ์๋์ผ๋ก @Autowired๊ฐ ๋ถ๋๋ค.
๐ setter ์ฃผ์ (Setter Injection)
๊ฐ์ฒด์ setter ๋ฉ์๋๋ฅผ ํตํด ์์กด์ฑ์ ์ฃผ์ ํ๋ ๋ฐฉ์
์์กด์ฑ์ ์ค์ ํ๊ธฐ ์ํด setter ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ์ธ๋ถ์์ ์์กด์ฑ์ ์ฃผ์ ํ๋ค.
private VoucherRepository voucherRepository;
@Autowired
public void setVoucherRepository(VoucherRepository voucherRepository) {
this.voucherRepository = voucherRepository;
}
๐ ํ๋ ์ฃผ์ (Field Injection)
์์กด์ฑ์ ํด๋์ค์ ๋ฉค๋ฒ ํ๋๋ก ์ง์ ์ฃผ์ ํ๋ ๋ฐฉ์
์ฃผ๋ก @Autowired ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ํ๋์ ์๋์ผ๋ก ์์กด์ฑ์ ์ฃผ์ ํ๋ค.
private VoucherRepository voucherRepository;
@Autowired
private VoucherRepository voucherRepository;
๐ค ์์ฑ์ ์ฃผ์ ๋ฐฉ์์ ์ฌ์ฉํ๋๋ฐ ์์ฑ์๊ฐ 2๊ฐ๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊น?
๋ ์์ฑ์ ์ค DI๋ฅผ ํ๋ ์์ฑ์์ @Autowired ์ ๋ ธํ ์ด์ ์ ๋ฌ์์ ๋ช ์์ ์ผ๋ก ์์กด์ฑ์ ์ฃผ์ ํ๋ค.
์ด๋ค DI ๋ฐฉ๋ฒ์ ์ ํํด์ผ ํ ๊น?
์คํ๋ง ๊ณต์ ๋ฌธ์์ ์์ฑ์ ์ฃผ์ ๋ฐฉ์์ ๊ถ์ฅํ๋ค๊ณ ์ฐ์ฌ์๋ค.
๊ทธ ์ด์ ๊ฐ ๋ฌด์์ผ๊น?
๐ ๋จ์ ํ ์คํธํ๊ธฐ์ ์ฉ์ดํ๋ค.
์์กด์ฑ์ ์ธ๋ถ์์ ์ฃผ์ ๋ฐ๊ธฐ ๋๋ฌธ์ ๋จ์ ํ ์คํธ์์ ๋ชจ์ ๊ฐ์ฒด(Mock Object)๋ฅผ ์ฌ์ฉํ์ฌ ์์กด์ฑ์ ์ฃผ์ ํ๋ ๊ฒ์ด ์ฝ๋ค.
๋ํ ๋ค๋ฅธ ์ฃผ์ ๋ฐฉ์์ ์์ ์๋ฐ ์ฝ๋๋ก ๋จ์ ํ ์คํธ๋ฅผ ์์ฑํ๋ ๊ฒ์ด ํ๋ค๋ค.
ํ ์คํธ์ฝ๋๋ Spring ์์์ ๋์ํ์ง ์์ผ๋ฏ๋ก ์์กด ๊ด๊ณ ์ฃผ์ ์ด ๋ฐ์ํ์ง ์์์ NPE(Null Pointer Exception)๋ฅผ ๋ฐ์ํ๋ค.
๐ ๋ถ๋ณ์ฑ์ ํ๋ณดํ๋ค.
์์กด์ฑ์ด ์ฃผ์ ๋ ๊ฐ์ฒด๋ ๋ณ๊ฒฝํ ์ ์๋ ๋ถ๋ณ ๊ฐ์ฒด๋ก ๋ง๋ค ์ ์๋ค.
์์กด์ฑ์ ๊ฐ์ฒด๊ฐ ์์ฑ๋ ๋ ์ฃผ์ ๋๋ฉฐ, ์ดํ์๋ ๋ณ๊ฒฝํ ์ ์๋ค.
์ด๋ ๊ฐ์ฒด์ ์์ ์ฑ๊ณผ ์์ธก ๊ฐ๋ฅ์ฑ์ ๋์ฌ์ค๋ค.
๐์ํ ์ฐธ์กฐ๋ฅผ ๋ฐฉ์งํ๋ค.
์ํ ์ฐธ์กฐ๋ฅผ ๋ฐํ์ ์์ ์ ๊ฐ์งํ๊ณ ์์ธ๋ฅผ ๋ฐ์์์ผ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
์์ฑ์ ์ฃผ์ ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ์์ ์ ์์กด์ฑ์ ์ฃผ์ ํ๊ณ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ ํ ์์กด์ฑ์ ์ฃผ์ ํ๋ค.
๋ฐ๋ผ์ ์์ฑ์ ์ฃผ์ ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ์์ ์์ ๋ฌธ์ ๋ฅผ ํ์งํ ์ ์๊ณ ๋๋จธ์ง ๋ฐฉ๋ฒ์ ์ค์ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ ์คํํ ๋ ๋ฌธ์ ๋ฅผ ์ ์ ์๋ค.
๐๊ฐ๋ฐ์์ ์์กด์ฑ ์ฃผ์ ์ค์ ๋ฐฉ์ง (final ํค์๋์ ์ฌ์ฉ)
๊ตฌํ์ฒด ์ฃผ์ ์ ๋ํ ์ฝ๋๋ฅผ ์์ด๋ฒ๋ฆฌ๊ณ ์ ์ง ์์๋ ์ปดํ์ผ ์์ ์์ ๋๋ฝ๋ ์์กด์ฑ์ ํ์ธํ ์ ์๋ค.
5. Beans Scope
์คํ๋ง ํ๋ ์์ํฌ์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฑ๊ธํค(Singleton)๊ณผ ํ๋กํ ํ์ (Prototype) ๋ ๊ฐ์ง ์ค์ฝํ๋ฅผ ์ง์ํ๋ค.
๊ทธ ์ด์ ๋ ์ด ๋ ๊ฐ์ง ์ค์ฝํ๊ฐ ๋๋ถ๋ถ์ ์ํฉ์์ ์๊ตฌ์ฌํญ์ ์ถฉ์กฑ์ํฌ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๐ ์ฑ๊ธํค ์ค์ฝํ
ํ๋์ ๋น ์ธ์คํด์ค๋ฅผ ์คํ๋ง ์ปจํ ์ด๋ ๋น ํ๋๋ง ์์ฑํ์ฌ ๊ด๋ฆฌํ๋ค.
๋ฐ๋ผ์ ๋์ผํ ๋น์ ์์ฒญํ ๋๋ง๋ค ํญ์ ๋์ผํ ์ธ์คํด์ค๊ฐ ๋ฐํ๋๋ค.
์ฑ๊ธํค์ ๊ธฐ๋ณธ ์ค์ฝํ๋ก ์ค์ ๋์ด ์์ผ๋ฉฐ, ๋ง์ ๊ฒฝ์ฐ์ ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ๊ณผ ์ฑ๋ฅ ํฅ์์ ์ํด ์ฑ๊ธํค ์ค์ฝํ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ถ์ฅ๋๋ค.
๐ ํ๋กํ ํ์
์ค์ฝํ
์์ฒญํ ๋๋ง๋ค ์๋ก์ด ๋น ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ค.
๋งค๋ฒ ์์ฒญํ ๋๋ง๋ค ์๋ก์ด ์ธ์คํด์ค๋ฅผ ๋ฐํํ๊ธฐ ๋๋ฌธ์ ๋์ผํ ํ์ ์ ๋น์ ์ฌ๋ฌ ๊ฐ ์์ฑํ๊ณ ์ฌ์ฉํด์ผ ํ ๋ ์ ์ฉํฉ๋๋ค.
์๋ฅผ ๋ค์ด, ๊ฐ๊ฐ์ ์์ฒญ์ ๋ํด ๋ณ๋์ ์ํ๋ฅผ ์ ์งํด์ผ ํ๋ ๊ฒฝ์ฐ์ ํ๋กํ ํ์ ์ค์ฝํ๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
๋น ์ค์ฝํ๋ฅผ ๋ณ๊ฒฝํ๋ ๋ฐฉ๋ฒ
ํด๋น ๋น์ ํด๋์ค๋ ๊ตฌ์ฑ ํ์ผ์ @Scope ์ ๋ ธํ ์ด์ ์ ์ถ๊ฐํ๊ณ ์ํ๋ ์ค์ฝํ ๊ฐ์ ์ค์ ํ๋ฉด ๋๋ค.
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON) // default
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
6. Lifes Cycle
Spring Application Context๋ ๊ฐ์ฒด์ ์์ฑ๊ณผ ์๋ฉธ, ์ฆ ์๋ช ์ฃผ๊ธฐ(Life Cycle)๋ฅผ ๊ด๋ฆฌํ๋ค.
applicationContext.close();
close()๋ฅผ ์ฌ์ฉํ๋ฉด applicationContext๊ฐ ์๋ฉธ๋๋ฉฐ, ์ปจํ ์ด๋์ ๋ฑ๋ก๋ ๋ชจ๋ ๋น๋ ํจ๊ป ์๋ฉธ๋๋ค.
์ด ๊ณผ์ ์ ์๋ฉธ์ ๋ํ callback์ด ๋์ํ๋ค.
Bean ์์ฑ ์๋ช ์ฃผ๊ธฐ ์ฝ๋ฐฑ
1. @PostConstruct ์ ๋ ธํ ์ด์ ์ด ์ ์ฉ๋ ๋ฉ์๋ ํธ์ถ
@PostConstruct
public void postConstruct() {}
2. Bean์ด InitializingBean ์ธํฐํ์ด์ค ๊ตฌํ์ afterPropertiesSet() ํธ์ถ
@Repository
public class MemoryVoucherRepository implements VoucherRepository, InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {}
}
3. @Bean ์ ๋ ธํ ์ด์ ์ initMethod์ ์ค์ ํ ๋ฉ์๋ ํธ์ถ
public class AppConfiguration {
@Bean(initMethod = "init")
public BeanOne beanOne() {
class BeanOne {
private void init() {}
}
}
Bean ์๋ฉธ ์๋ช ์ฃผ๊ธฐ ์ฝ๋ฐฑ
1. @PreDestory ์ ๋ ธํ ์ด์ ์ด ์ ์ฉ๋ ๋ฉ์๋ ํธ์ถ
@Override
public void destroy() throws Exception {}
2. Bean์ด DisposableBean ์ธํฐํ์ด์ค ๊ตฌํ์ destroy() ํธ์ถ
@Repository
public class MemoryVoucherRepository implements VoucherRepository, DisposableBean {
@PreDestroy
public void preDestroy() {}
}
3. @Bean ์ ๋ ธํ ์ด์ ์ destroyMethod์ ์ค์ ํ ๋ฉ์๋ ํธ์ถ
public class AppConfiguration {
@Bean(initMethod = "destroy")
public BeanOne beanOne() {
class BeanOne {
private void destroy() {}
}
}
Reference
Circular Dependencies in Spring
HashMap vs HashTable vs ConcurrentHashMap
Spring @ComponentScan - ํํฐ ์ ํ
[Spring] ์์ฑ์ ์ฃผ์ ์ ์ฌ์ฉํด์ผ ํ๋ ์ด์
[Spring] ๋ค์ํ ์์กด์ฑ ์ฃผ์ ๋ฐฉ๋ฒ๊ณผ ์์ฑ์ ์ฃผ์ ์ ์ฌ์ฉํด์ผ ํ๋ ์ด์ - (2/2)
'๐๏ธ ํ๋ก๊ทธ๋๋จธ์ค ๋ฐ๋ธ์ฝ์ค' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
SpringBoot Part1-5 (0) | 2023.06.26 |
---|---|
SpringBoot Part1-4 (0) | 2023.06.23 |
SpringBoot Part1-2 (0) | 2023.06.21 |
SpringBoot Part 1-1 (0) | 2023.06.21 |
ํ๋ ์์ํฌ๋ฅผ ์ํ JAVA - OOP (0) | 2023.06.11 |
๋๊ธ