Spring์ด ์คํ๋๋ ๋ฒ์ ํด๋ถํด๋ณด์.. (1)์์ ์ด์ด์ง๋๋ค.
refresh()ํ๋ค. << ํ์ฌ ์ฌ๊ธฐ!refresh() ๋ฉ์๋์์๋ ๋น ์ ์, ์์กด์ฑ ์ฃผ์ , ๋น ์์ฑ ๋ฑ๋ฑ ์คํ๋ง ์ปจํ ์ด๋๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ๋ค์ํ ์์ ์ ์งํํ๋ค. ์ ๋ฒ 1ํธ์์๋ Bean definition์ด ๋ฑ๋ก๋ Bean Factory๋ฅผ ๋ค๊ณ ์ค๋ ๊ฒ๊น์ง ํจ๊ป ์ง์ผ๋ดค๋ค.
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();
// -------------------------------------------- 1ํธ์์ ์ฌ๊ธฐ๊น์ง ์งํํ์! -------
// 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();
}
}
์ด์ ์์กด์ฑ ์ฃผ์ ๋ถํฐ ์คํ๊น์ง ์ด๋ป๊ฒ ์๋ํ๋์ง ์์๋ณด์.
์ค์ ๋ก ๋น ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์์ฑ๋ ๊ฐ์ฒด์ ์์กด์ฑ์ ์ฃผ์ ํ๋ ๋จ๊ณ์ด๋ค.
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize bootstrap executor for this context.
if (beanFactory.containsBean(BOOTSTRAP_EXECUTOR_BEAN_NAME) &&
beanFactory.isTypeMatch(BOOTSTRAP_EXECUTOR_BEAN_NAME, Executor.class)) {
beanFactory.setBootstrapExecutor(
beanFactory.getBean(BOOTSTRAP_EXECUTOR_BEAN_NAME, Executor.class));
}
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no BeanFactoryPostProcessor
// (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Call BeanFactoryInitializer beans early to allow for initializing specific other beans early.
String[] initializerNames = beanFactory.getBeanNamesForType(BeanFactoryInitializer.class, false, false);
for (String initializerName : initializerNames) {
beanFactory.getBean(initializerName, BeanFactoryInitializer.class).initialize(beanFactory);
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
try {
beanFactory.getBean(weaverAwareName, LoadTimeWeaverAware.class);
}
catch (BeanNotOfRequiredTypeException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to initialize LoadTimeWeaverAware bean '" + weaverAwareName +
"' due to unexpected type mismatch: " + ex.getMessage());
}
}
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
${ }๋ฅผ ์ค์ ๊ฐ์ผ๋ก ๋์ฒดํด์ฃผ๋ ์ญํ ์ ํ๋ค.public void preInstantiateSingletons() throws BeansException {
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
List<CompletableFuture<?>> futures = new ArrayList<>();
this.preInstantiationThread.set(PreInstantiation.MAIN);
this.mainThreadPrefix = getThreadNamePrefix();
try {
for (String beanName : beanNames) {
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
if (!mbd.isAbstract() && mbd.isSingleton()) {
CompletableFuture<?> future = preInstantiateSingleton(beanName, mbd);
if (future != null) {
futures.add(future);
}
}
}
}
finally {
this.mainThreadPrefix = null;
this.preInstantiationThread.remove();
}
if (!futures.isEmpty()) {
try {
CompletableFuture.allOf(futures.toArray(new CompletableFuture<?>[0])).join();
}
catch (CompletionException ex) {
ReflectionUtils.rethrowRuntimeException(ex.getCause());
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName, false);
if (singletonInstance instanceof SmartInitializingSingleton smartSingleton) {
StartupStep smartInitialize = getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
smartSingleton.afterSingletonsInstantiated();
smartInitialize.end();
}
}
}
๊ธฐ์กด์ ๋ฑ๋ก๋ bean definitions๋ฅผ ํตํด bean name๋ค์ ๊ฐ์ ธ์จ๋ค.
๊ทธ๋ฆฌ๊ณ Thread, Future์ ๋ณด์ํ๋ ๋น ์์ฑ, ์์กด์ฑ ์ฃผ์
์ ๋น ๋ฅด๊ฒ ํ๊ธฐ ์ํด ๋ณ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ํ๋ ๊ฒ ๊ฐ๊ณ ... try ๋ธ๋ก ๋ด์ ๋ฉ์๋๋ค์ ํตํด ๋น์ ์์ฑํ๋ ๊ฒ ๊ฐ๋ค.
CompletableFuture.allOf(futures.toArray(new CompletableFuture<?>[0])).join();์ ํตํด ๋น๋๊ธฐ ๋น ์์ฑ ์์
์ด ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ๋ค.
์ดํ for๋ฌธ์ผ๋ก bean name๋ณ๋ก afterSingletonsInstantiated()๋ฅผ ํธ์ถํ๋ค. ์ด๋ฆ๋ง ๋ณด์๋ ์ ์ ์๊ฒ ์ง๋ง, singleton ์ธ์คํด์ค๊ฐ ์์ฑ๋ ๋ค ํ์ํ ์ด๊ธฐํ ๋ก์ง์ ํ๋์ฉ ์คํํ๋ค.
๊ทธ๋ผ ์ด์ try ๋ธ๋ก ๋ด์ ๋ฉ์๋๋ค์ ํ๋์ฉ ๋ณด์.
์ฐ์ getMergedLocalBeanDefinition()
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null && !mbd.stale) {
return mbd;
}
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
getMergedLocalBeanDefinition()์ ํ์ฌ ๋น์ด child bean์ธ ๊ฒฝ์ฐ parent bean definition๊น์ง ์ฐพ์๋ด merged definition์ ๋ฐํํ๋ค. (๋ง์ฝ ๋ถ๋ชจ๊ฐ ์๋ bean์ธ ๊ฒฝ์ฐ ๊ทธ๋ฅ ์ค์ค๋ก๋ฅผ RootBeanDefinition์ผ๋ก ๋ณํํด์ ๋ฐํํ๋ค.)
RootBeanDefinition์ ํ์ธํด๋ณด๋ ๋ฐํ์์ ์ฌ์ฉํ๊ธฐ ์ํ ์ฌ๋ฌ bean definition๋ฅผ ํตํฉ(unified) bean definition์ด๋ผ๊ณ ํ๋ค. ๊ทธ๋ฌ๋๊น... child bean definition์ ์ฌ์ฉํ ๋, parent bean definition์ ์ผ์ผ์ด ์กฐํํ ํ์๊ฐ ์๋๋ก child bean definition์ parent bean definition์ ํฉ์ณ merge๋ ์ํ๋ก ๋ฐํํ๋ค๋ ๊ฒ์ด๋ค.
์ด๋ ๊ฒ ๋ฐ์์จ merged bean definition(์ดํ mbd)๊ฐ abstract(์ถ์)์ด ์๋๊ณ singleton์ด๋ฉด preInstantiateSingleton()๋ฅผ ์คํํ๋ค.
@Nullable
private CompletableFuture<?> preInstantiateSingleton(String beanName, RootBeanDefinition mbd) {
if (mbd.isBackgroundInit()) {
Executor executor = getBootstrapExecutor();
if (executor != null) {
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
getBean(dep);
}
}
CompletableFuture<?> future = CompletableFuture.runAsync(
() -> instantiateSingletonInBackgroundThread(beanName), executor);
addSingletonFactory(beanName, () -> {
try {
future.join();
}
catch (CompletionException ex) {
ReflectionUtils.rethrowRuntimeException(ex.getCause());
}
return future; // not to be exposed, just to lead to ClassCastException in case of mismatch
});
return (!mbd.isLazyInit() ? future : null);
}
else if (logger.isInfoEnabled()) {
logger.info("Bean '" + beanName + "' marked for background initialization " +
"without bootstrap executor configured - falling back to mainline initialization");
}
}
if (!mbd.isLazyInit()) {
try {
instantiateSingleton(beanName);
}
catch (BeanCurrentlyInCreationException ex) {
logger.info("Bean '" + beanName + "' marked for pre-instantiation (not lazy-init) " +
"but currently initialized by other thread - skipping it in mainline thread");
}
}
return null;
}
isBackgroundInit()) dependsOn์ ํตํด mbd๊ฐ ์์กดํ๊ณ ์๋ ๊ฐ์ฒด๋ค์ ํ์
ํ๊ณ , ํ๋์ฉ getํด ์จ๋ค... getBean()์ ํ๋จ์์ ์ถ๊ฐ ์์ ํ๊ฒ ๋ค.instantiateSingletonInBackgroundThread()๋ฅผ ์คํํด bean์ ๊ฐ์ ธ์จ๋ค. ๋ง์ฝ lazyInit ์ค์ ์ด ๋์ด์๋ค๋ฉด future ๊ฐ์ด ์๋ null์ ๋ฐ์๊ฐ๋ค.instantiateSingleton()๋ฅผ ์คํํ๋ค.private void instantiateSingletonInBackgroundThread(String beanName) {
this.preInstantiationThread.set(PreInstantiation.BACKGROUND);
try {
instantiateSingleton(beanName);
}
catch (RuntimeException | Error ex) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to instantiate singleton bean '" + beanName + "' in background thread", ex);
}
throw ex;
}
finally {
this.preInstantiationThread.remove();
}
}
instantiateSingletonInBackgroundThread()์ ์ค๋ ๋์์ instantiateSingleton()๋ฅผ ์คํํ๋ ๋ฉ์๋์ด๋ฉฐ,
private void instantiateSingleton(String beanName) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof SmartFactoryBean<?> smartFactoryBean && smartFactoryBean.isEagerInit()) {
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
instantiateSingleton()์ getBean()์ ํตํด bean์ ๊ฐ์ ธ์จ๋ค.
Bean์ ์ด๋ป๊ฒ ๊ฐ์ ธ์ค๋์ง ์์๋ณผ ์ฐจ๋ก๋ค.
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, null, args, false);
}
๋จ์ํ๋ค. ์ผ๋จ doGetBean์ ํธ์ถํ๋ค.
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object beanInstance;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory abf) {
return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
} else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new "์๋ต";
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
} // ์๋ต
}
throw ex;
}
}
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// ์๋ต
return adaptBeanInstance(name, beanInstance, requiredType);
}
์ ๋จ์ํ๋ค.. ์ฝ๋๊ฐ ๋๋ฌด ๊ธธ์ด ์ผ๋ถ ์ฝ๋๋ฅผ ์๋ตํ๋ค.
transformedBeanName(name);์ ํตํด bean name์ ์ ๊ทํํ๋ค.getSingleton(beanName);์ ํตํด ์ด๋ฏธ ์์ฑ๋ ๋น์ด ์๋์ง ํ์ธํ๋ค.getParentBeanFactory();๋ฅผ ํตํด Parent Bean Factory๋ฅผ ์ฐพ์์จ๋ค.isDependent()๋ฅผ ํตํด ์ํ ์ฐธ์กฐ ๋ฌธ์ ๋ฅผ ๋จผ์ ํ์ธํ ๋ค, ์ํ ์ฐธ์กฐ ๋ฌธ์ ๊ฐ ์๋ค๋ฉด ์์กดํ๊ณ ์๋ ๋น์ ๋จผ์ ๊ฐ์ ธ์จ๋ค.createBean()ํ๋ค.createBean() ํ๋ค.@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock.
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
if (!this.singletonLock.tryLock()) {
// Avoid early singleton inference outside of original creation thread.
return null;
}
try {
// Consistent creation of early reference within full singleton lock.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
// Singleton could have been added or removed in the meantime.
if (this.singletonFactories.remove(beanName) != null) {
this.earlySingletonObjects.put(beanName, singletonObject);
}
else {
singletonObject = this.singletonObjects.get(beanName);
}
}
}
}
}
finally {
this.singletonLock.unlock();
}
}
}
return singletonObject;
}
lock์ ์ฌ์ฉํ์ฌ ์ํ๋ bean์ด ์กด์ฌํ๋์ง ํ์ธํ๋ค.
singletonObjects์์ beanName์ ๊ธฐ๋ฐ์ผ๋ก ๊ฐ์ ธ์๋ณธ๋ค.earlySingletonObjects์์ beanName์ ๊ธฐ๋ฐ์ผ๋ก ๊ฐ์ ธ์๋ณธ๋ค.allowEarlyReference์ธ ๊ฒฝ์ฐ, ๋ฝ์ ๊ฑธ๊ณ singletonObject๋ฅผ ์๋ก ๊ฐ์ ธ์ค๊ณ earlySingletonObjects์ ์๋กญ๊ฒ ์ง์ด๋ฃ๋๋ค. ๐ doCreateBean()์์ ์ํ ์ฐธ์กฐ์ฑ์ ์๊ธฐํ ๋ ๋ ๋์จ๋ค.์ ์ด๋ ๊ฒ ํ๋ ์๊ฐํด๋ดค๋๋, B ๋น์ ์ฐธ์กฐํ๋ A ๋น๊ณผ A ๋น์ ์ฐธ์กฐํ๋ B ๋น์ด ์์ ๋์ ์ํ ์ฐธ์กฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์์ด๋ค. A ๋น๋ B ๋น๋ ์๋ก ์์ ํ ์๋ฃ๋ ๋น์ ์ฃผ์
๋ฐ์ผ๋ ค๊ณ ๋ง ํ๋ค๋ฉด ์์ํ ์๋ก๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ฒ ๋๋ค.
๊ทธ๋์ ์ข ๋ ์์ฑ๋๋๋ผ๋ factory์ ์๋ ๋๋ค๋ฅผ ์คํํด ๋ฏธ๋ฆฌ ์ฃผ์
๋ฐ๊ณ , earlySingletonObjects์ ๋ฃ์ด๋๋๋ค. ๋์ค์ ์๊ฒ ๋๊ฒ ์ง๋ง(doCreateBean()), ๋ชจ๋ ๋น๋ค์ ์ด๊ธฐํ๋ฅผ ์งํํ๊ธฐ ์ ํ๋ก earlySingletonObjects๋ฅผ ํ ๋ฒ ํ์ธํ๋ค.
์ํ ์ฐธ์กฐ ๋ฌธ์ ํด๊ฒฐ ์ ๋๋๋ฐ? -> ๊ทธ๊ฑด ์์ฑ์ ์ฃผ์ ๋ง์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ด๋ค. ์์ฑ์ ์ฃผ์ + ํ๋ ์ฃผ์ (ํน์ ์์ฑ์ ์ฃผ์ + ์ธํฐ ์ฃผ์ ) ์์ด์ ์ฌ์ฉํ๋ฉด ์ํ ์ฐธ์กฐ๋ฅผ ํ ์๋ ์๋ค. (์ข์ ์ค๊ณ๋ ์๋)
singletonObjects์๋ ์์ฑ์ด ์์ ํ ์๋ฃ๋ ๋น, earlySingletonObjects์ ์์ฑ์ ๋์ง๋ง ์ด๊ธฐํ๋ ๋์ง ์์ ๋น, singletonFactories์๋ ๋น ํฉํ ๋ฆฌ๊ฐ ์ ์ฅ๋์ด ์๋ค๊ณ ํ๋ค.
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
// bean defintion ํ์ ๊ณผ ๊ด๋ จ๋ ์ฝ๋ ์๋ต
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
} // ์๋ต
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
} // ์๋ต, ๋ง์ฐฌ๊ฐ์ง๋ก log ๊ด๋ จ๋ ๋ถ๋ถ์ ์ผ๋ถ ์๋ตํ๋ค.
}
resolveBeforeInstantiation()๋ฅผ ํตํด bean์ด ๋ฐํ๋๋ฉด ๋ ์ด์ ์ถ๊ฐ ์์
์ ํ์ง ์๋๋ค. ์ค์ ๋น ๋์ ํ๋ก์ ๋ฑ ๋ค๋ฅธ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ ๋ถ๋ถ์ด๋ค.doCreateBean() gogoprotected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.markAsPostProcessed();
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
} // ์๋ต
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = CollectionUtils.newLinkedHashSet(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException("์๋ต");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
} // ์๋ต, ๋ง์ฐฌ๊ฐ์ง๋ก log ๊ด๋ จ๋ ๋ถ๋ถ์ ์ผ๋ถ ์๋ตํ๋ค.
return exposedObject;
}
createBeanInstance()์ผ๋ก bean instance๋ฅผ ์์ฑํ๋ค. (mbd๊ฐ ์ฑ๊ธํค์ธ ๊ฒฝ์ฐ, factoryBeanInstanceCache์์ ํด๋น ๋น ์ธ์คํด์ค๋ฅผ ์ ๊ฑฐํ๊ณ ์ฌ์ฌ์ฉ)applyMergedBeanDefinitionPostProcessors()๋ก post processor๋ฅผ ์ ์ฉํ๋ค. ๊ทธ๋ฆฌ๊ณ markAsPostProcessed()๋ก post processed ๋์์์ ๋งํนํ๋ค.SingletonFactory์ ๋น์ ๋ฐํํ ์ ์๋ ๋๋ค์ธ factory๋ฅผ ์ ์ฅํด๋๋ค.populateBean()๋ก ์์กด์ฑ์ ์ฃผ์
ํ๋ค. ์๋์์ ์ถ๊ฐ๋ก ์ค๋ช
ํ๋ค.initializeBean()์ผ๋ก ๋น์ ์ด๊ธฐํ ๊ด๋ จ ๋ฉ์๋๋ค์ ์คํํ๋ค. @PostConstruct ์ด๋
ธํ
์ด์
์ด ์ฌ๊ธฐ์ ์คํ๋๋ค! applyBeanPostProcessorsAfterInitialization()๋ฅผ ํตํด AOP Proxy๋ ์ฌ๊ธฐ์ ์ ์ฉ๋๋ค. (๊ผญ ์ฌ๊ธฐ์ ๋ชจ๋ AOP Proxy๊ฐ ์ ์ฉ๋๋ ๊ฒ์ ์๋๊ณ , getEarlyReference()์์๋ ์์ฑ๋๋ ๊ฒฝ์ฐ๋ ์กด์ฌํ๋ค. ์ํ ์์กด์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ๊ฑด๋ฐ, ๋ง์ฝ early..์์ ๋จผ์ ์์ฑ๋๋ค๋ฉด ์ฌ๊ธฐ์ ์ฌ์ฌ์ฉํ๋ค.)earlySingletonReference๊ณผ ํ์ฌ bean์ ๋น๊ตํ๋ค. earlySingletonReference๋ getSingleton(beanName, false);์ ํตํด ๊ฐ์ ธ์ค๋๋ฐ, ์ด๋ฌ๋ฉด singletonFactories๋ ์ ์ธํ singletonObject์ earlySingletonObjects๋ง ํ์ธํ๊ฒ ๋๋ค. (๋ง์ฝ ๋ค๋ฅธ ๋น์ด ์์กด์ ์ํด factory์์ ๋น์ ๋นผ๋์ผ๋ฉด singletonObject๋ earlySingletonObjects์ ๋ฑ๋ก๋๋๊น)!allowRawInjectionDespiteWrapping(ํ๋ก์ ๋ง๊ณ ์๋ณธ ๋น ์ฌ์ฉ ๋ถ๊ฐ) ๊ฒฝ์ฐ) ํ์ฌ๋ initializeBean()๋ฅผ ํตํด AOP๊ฐ ์ ์ฉ๋ ์ํ์ธ๋ฐ, ๋ค๋ฅธ ๋น์ ๋ค๋ฅธ ๋ฒ์ ์ ์ฌ์ฉํ๊ณ ์๋ค๋ ๊ฑฐ๋ค.removeSingletonIfCreatedForTypeCheckOnly, ๊ทธ๋ฌ๋๊น ํ์
์ฒดํฌ๋ง ํ๋ ค๊ณ ๋น์ ๊ฐ์ ธ๊ฐ๋ค๋ฉด ์ ๊ฒฝ ์ฐ์ง ์๋๋ค. ํ์ง๋ง ์ด ๋ชจ๋ ๊ฒ์ด ์ถฉ์กฑ๋์ด ์ํ ์์กด์ฑ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค๋ฉด, ์์ธ๋ฅผ ํฐ๋จ๋ฆฐ๋ค.protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new );
}
else {
// Skip property population phase for null instance.
return;
}
}
if (bw.getWrappedClass().isRecord()) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to a record");
}
else {
// Skip property population phase for records since they are immutable.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
if (hasInstantiationAwareBeanPostProcessors()) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
pvs = pvsToUse;
}
}
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
if (needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
postProcessAfterInstantiation()๋ก ์์กด์ฑ ์ฃผ์
์ ๊ฑด๋๋ฐ์ด์ผ ํ๋์ง ํ์ธํ๋ค.AUTOWIRE_BY_NAME ํน์ AUTOWIRE_BY_TYPE ๋ฑ ์ค์ ๋ ๊ฐ์ ๋ง์ถฐ ์ด๋ฆ์ด๋ ํ์
์ ๊ธฐ์ค์ผ๋ก ํ์ํ ๋น์ ๊ฐ์ ธ์ค๊ณ , property values์ ์ถ๊ฐํ๋ค. (XML)@Autowired, @Value, @Inject๋ฅผ ์ฒ๋ฆฌํ๋ค. (Annotation)protected void finishRefresh() {
// Reset common introspection caches in Spring's core infrastructure.
resetCommonCaches();
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches();
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
}
finishRefresh()์์๋ ์ด์ ํ์ ์๊ฒ ๋ ์บ์๋ค์ ์ ๊ฑฐํ๊ณ , LifecycleProcessor๋ฅผ ์์ฑํ๊ณ ์ด๊ธฐํํ๋ค.
Lifecycle processor๋ Lifecycle ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ๋น๋ค์ ๊ด๋ฆฌํ๋ค. Lifecycle์ ๊ตฌํํ ๋น๋ค์ start(), stop()์ ๊ตฌํํ๊ฒ ๋๋๋ฐ ์ด ๋ฉ์๋๋ค์ ํตํด์ Lifecycle processor๊ฐ ๋น์ ์์ํ๊ณ ์ข ๋ฃํ ์ ์๋ค.
๊ทธ๋ฆฌ๊ณ ๋ง์ง๋ง์ผ๋ก publishEvent()๋ฅผ ํตํด ์ปจํ ์ด๋๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์ด๊ธฐํ๋์์์ ์ธ๋ถ์ ์๋ฆฌ๊ฒ ๋๋ค. (์๋ง ์ด๋ฒคํธ ๋ฉํฐ์บ์คํฐ๋ก ์ด๋ฒคํธ๋ฅผ ๋ฐ์๋ณผ ์ ์์ ๊ฒ ๊ฐ๋ค.)
์์ฃผ ๊ธธ๊ณ ๊ธด ์ฌ์ ์ด์๋ค.. refresh()๊ฐ ๋๋๋ฉด ์ปจํ ์ด๋์ ๋น์ ์ค๋น๊ฐ ์๋ฃ๋ ๊ฒ์ด๊ณ , ์ด์ ๋ค์ ์ฒ์์ run() ๋ฉ์๋๋ก ๋์๊ฐ์...
refresh๊ฐ ๋๋๋ฉด ๋จ์ ์์ ์ ๋ช ๊ฐ ๋์ง ์๋๋ค.
์คํ๋ง ๋ถํธ ํ๊ฒฝ์ ์ต์ข _์ต์ข _์ต์ข _์ต์ข ์์ ์ ์ฒ๋ฆฌํ๋ค. ์ด๊ธฐํ ์์ ์ ๋ง๋ฌด๋ฆฌํ๊ณ ์ํ๋ฅผ ์ ๋ฆฌ, ์น ์๋ฒ๋ฅผ ๊ตฌ๋ํ๋ ๋ฑ์ ์์ ์ ํ๋ค.
์ปจํ ์ด๋๊ฐ ์์๋์์์ ์ด๋ฒคํธ๋ก ์๋ฆฐ๋ค.
์ต์ข ์ ์ผ๋ก CommandLineRunner๋ ApplicationRunner ๋น์ ํธ์ถํด ์ฌ์ฉ์ ์ ์ ์ด๊ธฐํ ๋ก์ง์ ์คํํ๋ค.
์ฌ์ค ์๋ ์คํ๋ง ๋ถํธ ์์ฒด ๋ด๋ถ ์ฝ๋๋ฅผ ์ง์ ๋ฏ์ด๋ณด๋ ๊ฒ์ ๋ํ ๊ณตํฌ์ฌ์ด ์ด์ง ์์๋ค... ๋ด๊ฐ ์์ฑํ์ง ์์ ์ฝ๋๋ฅผ ์ ์ฝ์ ์ ์์ด์ผ ํ๋ค๋ ๊ฑธ ์๊ณ ์์์๋ ๋ถ๊ตฌํ๊ณ ์ดํด๊ฐ ์ ์ ๋์ง ์์๊น ํ๋ ์๊ฐ์ด ์์๋๋ณด๋ค.
ํ์ง๋ง ์ฝ์ด๋ณด๋ฉฐ ์ฐจ๊ทผ์ฐจ๊ทผ ๋ฏ์ด๋ณด๋ ๊ทธ๋ฆฌ ์ด๋ ค์ด ์ผ๋ ์๋์๋ค! ๋จ์ํ ๊ณต์ ๋ฌธ์, ๊ธ ๊ฐ์ ๊ฑธ ์ฝ๋ค ๋ณด๋ฉด ๊ทธ๋์ ๋์ฒด ์ด๋ป๊ฒ ๊ตฌํํ ๊ฑฐ์ง? ๋ผ๋ ์๋ฌธ์ด ๊ฐ๋ ๋ค ๋๊ฐ ์์๋๋ฐ, ์ด์ ๊ณง๋ฐ๋ก ์ง์ ์ฝ๋๋ฅผ ๋ฏ์ด๋ด์ผ๊ฒ ๋ค ใ ใ
๊ทธ๋ฆฌ๊ณ ์ฃผ์, ๋ฉ์๋๋ช , ๋ณ์๋ช ์ด ์ผ๋ง๋ ์ค์ํ์ง ๋ฐฐ์ด ๊ฒ ๊ฐ๋ค. ๊ตฌ์ฒด์ ์ผ๋ก ์ด๋ป๊ฒ ๋์ํ๋์ง ๊ถ๊ธํด์ ๋ค์ด๊ฐ ๋ณธ ๊ฒ์ ์ ์ธํ๋ฉด, ์ฅ๊ฐํ๋ฉด ์์ฒญ๋๊ฒ ์น์ ํ ์ฃผ์๊ณผ ๋ฉ์๋๋ช , ๋ณ์๋ช ์ ํตํด ๋๋ต ์ด๋ค ๊ธฐ๋ฅ์ ํ๋ ๊ฑด์ง ์ฝ๊ฒ ์ง์ํ ์ ์์๋ค.
ํ๋ก์ ํธ ํ ๋ ์ฃผ์, ๋ฉ์๋๋ช , ๋ณ์๋ช ์ ๋ ์ ์คํ ์์ฑํด์ผ๊ฒ ๋ค๋ ์๊ฐ์ด ๋ค์๋ค!
ํ๋ฆฐ ์ ์ง์ /์ง๋ฌธ ๋๊ธ ์ธ์ ๋ ํ์์ ๋๋ค_ใธ(โญ-โญ)โจ ๋.