2025.10.02
์ฐ์ ๊ฐ๋จํ๊ฒ Spring, IoC, DI, ๊ทธ๋ฆฌ๊ณ Bean์ ๋ํด ์ง๊ณ ๋์ด๊ฐ๋ณด์.
์คํ๋ง์ ์๋ฐ ํ๋ซํผ์ ์ํ ์ ํ๋ฆฌ์ผ์ด์
ํ๋ ์์ํฌ์ด๋ค.
์ ํ๋ฆฌ์ผ์ด์
ํ๋ ์์ํฌ๋ผ ํจ์ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ฐ๋ฐํ๋ ๋ฐ ํ์ํ ๊ธฐ์ด ๊ธฐ๋ฅ๋ค์ ์ ๊ณตํ๋ ๊ณจ์กฐ ๊ฐ์ ์ญํ ์ด๋ค.
IoC ์ปจํ ์ด๋๋ ์คํ๋ง์ ํต์ฌ ๋ชจ๋ ์ค ํ๋์ด๋ค. IoC ์ปจํ ์ด๋๋ ๋ญ๊น. IoC ์ปจํ ์ด๋๋ ๊ฐ์ฒด๋ค ๊ฐ์ ์์กด์ฑ๊ณผ ์๋ช ์ฃผ๊ธฐ(์์ฑ, ์ ๊ฑฐ)๋ฅผ ๋ด๋นํ๋ ๋ชจ๋์ด๋ค.
IoC๋ ์ ์ด์ ์ญ์ (Inversion of Control)์ด๋ผ๋ ๋ป์ด๋ค. ๋ฌด์จ ์ ์ด๋ฅผ ์ญ์ ํ๋๋ฉด, ๊ฐ์ฒด์ ์์กด์ฑ์ ๋ํ ์ ์ด์ด๋ค. ๊ฐ์ฒด์ ์์กด์ฑ์ ๊ฐ๋ฐ์๊ฐ ๊ตฌํํ์ง ์๊ณ ์คํ๋ง ์ปจํ ์ด๋๊ฐ ๋ด๋นํ๊ธฐ ๋๋ฌธ์ด๋ค.
์คํ๋ง์ผ๋ก ๋ฐฑ์๋ ํ๋ก์ ํธ๋ฅผ ํด๋ดค๋ค๋ฉด ์๊ฒ ์ง๋ง ์ฝ๋๋ฅผ ์งค ๋, ์ฐ๋ฆฌ๋ Service์์ ๋ถ๋ฅด๋ Repository ์ฝ๋๋ฅผ new๋ก ์์ฑํ์ง ์๋๋ค.

์์ฃผ ํํ๊ฒ ๋ณผ ์ ์๋ ์ฝ๋์ด๋ค. @RequiredArgsConstructor๋ฅผ ๋ฌ๊ณ , ๋ฐ์๋ final๋ก Service์ ๊ผญ ํ์ํ ๋ค๋ฅธ ๊ฐ์ฒด๋ค์ ๋ณ์๋ก ์ง์ ํด๋๋ค. ๋๋ ์์ฑ์๋ฅผ ์์ฑํ ์ ๋, setter๋ก ์ด ๋ณ์๋ค์ new๋ก ์์ฑํ์ฌ ์ง์ด๋ฃ์ด์ค ์ ๋ ์๋ค. ๊ทธ๋ฐ๋ฐ๋ ์ฝ๋๋ ์ ์๋ํ๋ค.
๋ด๊ฐ ๋ชจ๋ฅด๋ ์ฌ์ด IoC ์ปจํ
์ด๋๊ฐ DI๋ก ๋ฌผ๋ฐ์์
์ ํด์ค ๊ฒ์ด๋ค.
DI๋ Dependency Injection, ์์กด์ฑ ์ฃผ์ ์ด๋ค. IoC์ ๋ญ๊ฐ ๋ค๋ฅธ ๊ฑธ๊น ์ถ๊ฒ ์ง๋ง, IoC๋ ์ข ๋ ์ถ์์ ์ธ ๊ฐ๋ ์ผ๋ก ์คํ๋ง์์ ์ถ๊ตฌํ๋ ์ ์ด๋ฅผ ์ญ์ ์์ผ์ผ ํ๋ค๋ ์ฒ ํ์ด๋ผ๋ฉด DI๋ IoC๋ฅผ ์คํํ๋ ๊ตฌ์ฒด์ ์ธ ๋ฐฉ๋ฒ์ด๋ค.
์์์ ์ด์ฌํ ๋งํ ์ ์ด์ ์ญ์ , ์์กด์ฑ ์ฃผ์ ์ ํ ๋ ์ฌ์ฉํ๋ ๊ฐ์ฒด๋ค์ด ์ ๋ถ Bean์ด๋ค. ์ฆ, Bean์ ์คํ๋ง ํ๋ ์์ํฌ์์ ๊ด๋ฆฌํ๋ ๊ฐ์ฒด๋ผ๊ณ ํ ์ ์๊ฒ ๋ค.
๊ฐ๋ฐ์๊ฐ ์ปจํ ์ด๋์ ์์ฑํด์ค ๋น ์ค์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ํตํด์ ์์ฑ๋๋ค.
Spring Boot๊ฐ ์คํ๋๋ ๊ณผ์ ์ ํด๋ถํ๊ธฐ ์ ๊ผญ ํ์ํ ๊ฐ๋ ๋ค์ ๊ฐ๋ตํ ์ ๋ฆฌํ๋ค. ์ด์ Spring Boot๊ฐ ์ด๋ค ๊ณผ์ ์ ํตํด ์คํ๋๋์ง ํ ๋ฒ ์์๋ณด์.
ApplicationContext๊ฐ ์์ฑ๋๋ค.
ํน์ BeanFactory๊ฐ ์์ฑ๋์ง๋ง, ๋ณดํต์ ApplicationContext๋ฅผ ์ฌ์ฉํ๋ค. BeanFactory๊ฐ ํ์ํ ๊ธฐ๋ณธ์ ์ธ ๊ธฐ๋ฅ๋ง์ ์ ๊ณตํ๋ IoC ์ปจํ ์ด๋๋ผ๋ฉด ApplicationContext๋ BeanFactory๋ฅผ ํ์ฅํ์ฌ ๊ตญ์ ํ, ์ด๋ฒคํธ ๋ฐํ ๋ฑ๋ฑ ์ถ๊ฐ์ ์ธ ๊ธฐ๋ฅ์ ์ ๊ณตํ๊ธฐ ๋๋ฌธ์ด๋ค.
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
์์ฃผ์์ฃผ ๋ง์ด ๋ณธ ์ฝ๋๋ค.
์คํ๋ง(๋ถํธ) ์ ํ๋ฆฌ์ผ์ด์
์ ์คํํ ๋ ์ด run ๋ฉ์๋๋ฅผ ํตํด ์คํ๋๋ค. ์ด run ๋ฉ์๋๋ฅผ ๋ฏ์ด๋ณด์...

์ฃผ์์ ์์ฃผ ์น์ ํ๊ฒ ์ค๋ช ๋์ด ์๋ค. ์คํ ์ค์ธ ApplicationContext๋ฅผ ๋ฐํํด์ฃผ๋ ๋ฉ์๋๋ผ๊ณ ํ๋ค. ์ ์ผ ๊ด๋ จ ์์ด๋ณด์ด๋ ๊ฑด createApplicationContext()์ด๋ค.
protected ConfigurableApplicationContext createApplicationContext() {
return this.applicationContextFactory.create(this.properties.getWebApplicationType());
์์ง refresh ๋์ง ์์ Application Context๋ฅผ ๋ฐํํ๋ค๊ณ ํ๋ค. ๊ทธ๋ผ refresh์์๋ ์ด๋ค ์์ ์ ํ๋ ๊ฑธ๊น?
refresh()์์๋ ๊ฐ๋ฐ์๊ฐ ์์ฑํด์ค XML, ์ด๋
ธํ
์ด์
, config ํ์ผ ๋ฑ์ ์ฝ์ด์์ Bean์ ์ ์ํ๋ค. (๊ทธ๋ฆฌ๊ณ ๋์ค์ DI๋ ํ๊ณ ์์ฑ๋ ํด์ค๋ค!) refresh ๋ฉ์๋์ ์ฝ๋ ์ ๋ฌธ์ ์๋์ ๊ฐ๋ค.
public void refresh() throws BeansException, IllegalStateException {
this.startupShutdownLock.lock();
try {
this.startupShutdownThread = Thread.currentThread();
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (RuntimeException | Error ex ) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
contextRefresh.end();
}
}
finally {
this.startupShutdownThread = null;
this.startupShutdownLock.unlock();
}
}
๊ธธ๋ค.. ๊ทธ๋ฆฌ๊ณ ์ฃผ์์ด ์์ฃผ์์ฃผ ์น์ ํ๊ฒ ๋ฌ๋ ค์๋ค. ์คํํ๋ ๋ฉ์๋๊ฐ ๊ฐ์ ์ด๋ค ์ญํ ์ ํ๋์ง ์ ๋ฆฌํด๋ณด๊ฒ ๋ค.
obtainFreshBeanFactory()์ ๋ด๋ถ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ๋ค.
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
Bean factory๋ฅผ refreshํ ๋ค์ ๊ฐ์ ธ์ค๋ ๋ฏํ๋ค. refreshBeanFactory()์์๋ ๋ฌด์์ ํ ๊น?
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
beanFactory.setApplicationStartup(getApplicationStartup());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
๋จผ์ ๊ธฐ์กด์ bean factory๊ฐ ์กด์ฌํ๋ฉด bean๋ค์ ์ ๋ถ ์ ๊ฑฐํ๊ณ bean factory๋ ๋ซ๋๋ค.
์ดํ bean factory๋ฅผ ์์ฑํ๊ณ , ํด๋น bean factory์ serialization id, bean definition override๋ฅผ ํ์ฉํ๋์ง, circular reference๋ฅผ ํ์ฉํ๋์ง ์ฌ๋ถ ๋ฑ์ ์ค์ ํ๋ค.
์ดํ loadBeanDefinitions()๋ก ๋น ์ ์๋ฅผ ๋ถ๋ฌ์จ๋ค.
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
loadBeanDefinitions()๋ฅผ ๊ตฌํํ ๋ฉ์๋๊ฐ ๋ง์๋ค. ์์ฒ๋ผ XML์์ ๋ถ๋ฌ์ค๋ ๋ฉ์๋, Annotation์ ๊ธฐ๋ฐ์ผ๋ก ๋ถ๋ฌ์ค๋ ๋ฉ์๋, Groovy์์ ๋ถ๋ฌ์ค๋ ๋ฉ์๋ ๋ฑ์ด ์์๋ค. Spring Boot์์๋ Annotation์ ๊ธฐ๋ฐ์ผ๋ก ๋์ํ๋ฏ๋ก AnnotationConfigWebApplicationContext ํ์ผ์ ์์ฑ๋ loadBeanDefinitions()๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ค๋ช
ํ๊ฒ ๋ค.
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory);
ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory);
BeanNameGenerator beanNameGenerator = getBeanNameGenerator();
if (beanNameGenerator != null) {
reader.setBeanNameGenerator(beanNameGenerator);
scanner.setBeanNameGenerator(beanNameGenerator);
beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
}
ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver();
if (scopeMetadataResolver != null) {
reader.setScopeMetadataResolver(scopeMetadataResolver);
scanner.setScopeMetadataResolver(scopeMetadataResolver);
}
if (!this.componentClasses.isEmpty()) {
if (logger.isDebugEnabled()) {
logger.debug("Registering component classes: [" +
StringUtils.collectionToCommaDelimitedString(this.componentClasses) + "]");
}
reader.register(ClassUtils.toClassArray(this.componentClasses));
}
if (!this.basePackages.isEmpty()) {
if (logger.isDebugEnabled()) {
logger.debug("Scanning base packages: [" +
StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");
}
scanner.scan(StringUtils.toStringArray(this.basePackages));
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
for (String configLocation : configLocations) {
try {
Class<?> clazz = ClassUtils.forName(configLocation, getClassLoader());
if (logger.isTraceEnabled()) {
logger.trace("Registering [" + configLocation + "]");
}
reader.register(clazz);
}
catch (ClassNotFoundException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Could not load class for config location [" + configLocation +
"] - trying package scan. " + ex);
}
int count = scanner.scan(configLocation);
if (count == 0 && logger.isDebugEnabled()) {
logger.debug("No component classes found for specified class/package [" + configLocation + "]");
}
}
}
}
}
Annotation์ด ๋ฑ๋ก๋ ๋น์ ์ ์๋ฅผ ์ฝ์ด์ค๋ reader, class path์ ๋ฑ๋ก๋ bean definition๋ฅผ ์ฝ์ด์ค๋ scanner๋ฅผ ์ ์ธํ๊ณ beanNameGenerator๋ฅผ ์ค์ ํ๋ค. beanNameGenerator๋ bean definition์ ๋ถ์ฌํ ์ด๋ฆ์ ๋ํ ๊ท์น์ ์ ์ํ๋ค. ์ดํ bean definition์ ์ฝ์ด์ฌ ๋, @Scope ์ด๋ ธํ ์ด์ ์ ์ฝ์ด bean์ scope๋ฅผ ๊ฒฐ์ ํ๋ scopeMetadataResolver๋ฅผ ๋ฑ๋กํ๋ค.
์ค์ ๋๊ตฌ(beanNameGenerator, scopeMetadataResolver)๋ฅผ ๋ฑ๋กํ๊ณ ๋๋ฉด ์ค์ ๋ก reader, scanner๋ฅผ ์ฌ์ฉํ์ฌ bean factory์ bean definition์ ๋ฑ๋กํ๋ค.
this.componentClass์ ๋ฑ๋ก๋์ด ์๋ ํด๋์ค ๋ชฉ๋ก์ reader๋ก bean definition์ ๋ฑ๋กํ๋ค.
๋ฉ์ธ ์ ํ๋ฆฌ์ผ์ด์ ํด๋์ค(@SpringBootApplication)์ @Configuration์ด ๋ถ์ ํด๋์ค๊ฐ ์ด ์์ ์ ๋ก๋ฉ๋๋ค.
this.basePackages๋ฅผ scanner๋ฅผ ์ฌ์ฉํ์ฌ ์ค์บํ๊ณ , ์ค์บ ๊ณผ์ ์์ ๋ฐ๊ฒฌ๋ ๋ชจ๋ ์ปดํฌ๋ํธ ํด๋์ค๋ฅผ bean definition์ ๋ฑ๋กํ๋ค.
Base package ์๋์ ์๋ธ ํจํค์ง๋ค์ ํ์ํ์ฌ @Component, @Service ๋ฑ๋ฑ ์ด๋ ธํ ์ด์ ์ด ๋ถ์ ํด๋์ค๋ฅผ bean definition์ผ๋ก ๋ฑ๋กํ๋ค. Base package๋ ์๋์ผ๋ก @SpringBootApplication์ด ์ด๋ ธํ ์ด์ ์ด ์์นํ ํจํค์ง๋ก ์ค์ ๋๋ค.
config location์ด class์ธ ๊ฒฝ์ฐ reader๋ฅผ ํตํด ๋ฑ๋กํ๊ณ package์ธ ๊ฒฝ์ฐ scanner๋ฅผ ํตํด ๋ฑ๋กํ๋ค.
Context์ ๋ฑ๋ก๋์ด ์๋ bean definition์ ๋ก๋ํ ์ ์๋ ์ถ๊ฐ์ ์ธ ์์ค์ ๊ฒฝ๋ก, ์ด๋ฆ์ ๋งํ๋ค.
์ด๋ฌํ ๊ณผ์ ์ ๊ฑฐ์ณ bean definition์ bean factory์ ๋ฑ๋กํ ๋ค, ์ด bean factory๋ฅผ ๋ค๊ณ ๋์์จ๋ค.
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}
Bean factory์ ์ค์ ์ ๋ถ์ฌํ๋ค. classLoader bean์ ๋ฑ๋กํ๊ธฐ๋ ํ๊ณ ... ๋๋ฌด ๊ธธ์ด์ ์๋ตํ๊ฒ ๋ค.
Bean Post Processor๋ฅผ ๋ฑ๋กํ๊ณ ๋ค์ํ ์ค์ ์ ์งํํ๋ค.
postProcessBeanFactory()๋ก ์์ฑ๊ฐ ์์ ์ ์งํํ๋ค. (์์ postProcessBeanFactory๊ณผ๋ ๋ค๋ฅธ ๋ฉ์๋๋ค.)Bean Post Processor๋ค์ ์ฐ์ ์์์ ๋ฐ๋ผ ๋ถ๋ฅํด bean factory์ ๋ฑ๋กํ๋ค.
BeanFactoryPostProcessor์ BeanPostProcessor๊ฐ ์ด๋ฆ์ด ์ ์ฌํด์ ํท๊ฐ๋ฆด ์ ์์ ๊ฒ ๊ฐ๋ค...(์ฌ์ค ๋ด๊ฐ ๊ทธ๋ฌ๋ค.)
์ด๋ฆ๊ณผ ์ฝ๋๋ก ํ์ ํด๋ณด์๋ฉด...
์ ์๋ "Factory"์ post processor์ด๋ฉฐ, ์ด๋ฆ๋ง ๋ณด๋ฉด Factory์์ post process๋ฅผ ์งํํ๋ ๊ฑฐ๋ bean์ด ์์ฑ๋๊ธฐ ์ ์ ์คํ๋ ๊ฒ ๊ฐ๋ค. ๋ด๋ถ์ ์กด์ฌํ๋ ์ ์ผํ ๋ฉ์๋ postProcessBeanFactory()์ ์ฃผ์์ ์ฝ์ด๋ณด๋ Application Context์ internal bean factory์ ๊ธฐ๋ณธ์ ์ธ ์ด๊ธฐํ๊ฐ ๋๋ ๋ค bean factory๋ฅผ ์์ ํ๋ค๊ณ ํ๋ค. ๋จ, ๋น ์ค์ ์ ๋ชจ๋ ๋ก๋ฉ๋์ด ์์ด์ผ ํ๋ ๋น ์ธ์คํด์คํ๋ ์์ง ์งํ๋๋ฉด ์ ๋๊ณ ... eager ์ด๊ธฐํ๋๋ ๋น๋ค์ ์์ฑ์ overrideํ๊ฑฐ๋ ์ถ๊ฐํ๋ ๊ฑธ ํ์ฉํ๋ค๊ณ ํ๋ค.
BeanPostProcessor ๋ด๋ถ์๋ postProcessBeforeInitialization(), postProcessAfterInitialization() ๋ฉ์๋๊ฐ ์กด์ฌํ๋ค. postProcessBefore~์ ์๋ก์ด ๋น ์ธ์คํด์ค์ ์ด๊ธฐํ ์ฝ๋ฐฑ์ด ์งํ๋๊ธฐ ์ ์ ์ด ๋ฉ์๋๋ฅผ ์ ์ฉํ๋ค.(์ด๋ฏธ ํ๋กํผํฐ ๊ฐ์ ์ฃผ์
๋จ) postProcessAfter~์ ๋น ์ธ์คํด์ค๊ฐ ์ด๊ธฐํ ๋ ํ ์ ์ฉ๋๋ค. ์๋ง ๋น์ด ์์ฑ๋ ์ /ํ๋ก ๋์ํ๋ ๊ฒ ๊ฐ๋ค.
์คํ์ค๋ฒํ๋ก์ฐ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ์๋ฉด
BeanFactoryPostProcessor๋
- ๋น ์ ์ ๋ก๋ && ๋น ์์ฑ(์ธ์คํด์คํ) ์ ์ ํธ์ถ
- eager ์ด๊ธฐํ๋๋ ๋น์๋ ์์ฑ์ ์ฌ์ ์, ์ถ๊ฐํ๋ ์ฉ๋
BeanPostProcessor๋
- ๋น์ ์๋ํ๊ธฐ ๋๋ฌธ์ ๋น ์ธ์คํด์คํ๋ฅผ ํ ๋ ์๋
๊ทธ๋ฌ๋ฉด Bean Definition โ BeanFactoryPostProcessor โ BeanPostProcessor.postProcessBeforeInitialization โ Bean instantiate โ BeanPostProcessor.postProcessAfterInitialization ๋๋ต ์ด๋ฐ ์์๊ฐ ๋๋ ๊ฒ ๊ฐ๋ค.
BeanPostProcessor ๋ด๋ถ ๋ฉ์๋๋ค์ ํ๋ ๋ฐฉ์์ด ํ๋ก์์๋ ์ ์ฌํ ๊ฒ ๊ฐ์ ์ถ๊ฐ๋ก ์ฐพ์๋ณด๋, ํด๋น ๋ฉ์๋๋ค์ด ๋ฐํํ๋ ๊ฐ์ฒด๊ฐ ๋น์ผ ์๋, ํ๋ก์๋ก ๊ฐ์ผ ๋น์ผ ์๋ ์์ด AOP ๊ธฐ๋ฅ์ด ์ฌ๊ธฐ์ ๊ตฌํ๋๋ค๊ณ ํ๋ค. (์คํ๋ง ๋งํฌ ์ฐธ์กฐ)
๊ตญ์ ํ(i18n) ๊ธฐ๋ฅ์ ๋ด๋นํ๋ ๋ฉ์์ง ์์ค ๋น์ ์ด๊ธฐํํ๋ค.
ApplicationContext๊ฐ BeanFactory์ ๋ค๋ฅธ ์ ์ค ํ๋๊ฐ ์ด ๊ตญ์ ํ ์ง์์ด๋ค!
์ ํ๋ฆฌ์ผ์ด์ ์ด๋ฒคํธ(์ปจํ ์คํธ ์ด๊ธฐํ, ์ฌ์ฉ์ ์ ์ ์ด๋ฒคํธ ๋ฑ)๋ฅผ ๋ฉํฐ์บ์คํธํ๋ ๋น์ ์ด๊ธฐํํ๋ค.
๊ธฐํ ์คํ์ ๋น๋ค์ ์ด๊ธฐํํ๋ค.
์ด๋ฒคํธ ๋ฆฌ์ค๋ ํ์ ์ ๋น๋ค์ ์ฐพ์์ ์ด๋ฒคํธ ๋ฉํฐ์บ์คํฐ์ ๋ฑ๋กํ๋ค.
ํ๋ฆฐ ์ ์ง์ /์ง๋ฌธ ๋๊ธ ์ธ์ ๋ ํ์์ ๋๋ค_ใธ(โญ-โญ)โจ