參考:https://javadoop.com/post/spring-ioc#customizeBeanFactory
public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, ApplicationContext parent)
throws BeansException {
super(parent);
Assert.notNull(paths, "Path array must not be null");
Assert.notNull(clazz, "Class argument must not be null");
this.configResources = new Resource[paths.length];
for (int i = 0; i < paths.length; i++) {
this.configResources[i] = new ClassPathResource(paths[i], clazz);
}
refresh();
}
1京办、 首先會初始化一個ApplicationContext蒜撮,其實是一個BeanFactory辰妙,然后調(diào)用他的refresh()方法進行初始化
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 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);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// 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 (BeansException 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 {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
2晦雨、 在refresh方法中會先來個鎖初狰,防止在refresh還沒有結(jié)束的時候又去啟動或者銷毀容器秫筏。
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
3诱鞠、 之后解析配置文件里面的bean定義,將它包裝成一個beandefination保存到beanfactory中这敬,保存在defaultlistablebeanfactory的beandefinationmap中航夺。這里說的 Bean 還沒有初始化,只是配置信息都提取出來了崔涂。
4阳掐、之后注冊一些回調(diào),一些監(jiān)聽器冷蚂,和一些鉤子方法用來擴展
// 初始化所有的 singleton beans
//(lazy-init 的除外)
finishBeanFactoryInitialization(beanFactory);
5缭保、調(diào)用finishBeanFactoryInitaization實例化bean
先進行實例化,如果不存在方法覆寫蝙茶,那么就使用反射進行實例化艺骂,否則使用CGLIB。如果有需要覆蓋或者動態(tài)替換的方法使用Cglib進行動態(tài)代理隆夯,如果沒有需要動態(tài)改變的方法那就直接使用反射進行實例化钳恕。所謂的動態(tài)替換或覆蓋的情況,就是使用了replace或者lookup的配置方法蹄衷。這兩個方法的作用就是在調(diào)用目標(biāo)方法的時候苞尝,對調(diào)用過程進行攔截,調(diào)用實現(xiàn)增強功能的攔截器宦芦,返回原來實例的代理宙址。
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
// 如果 bean 實現(xiàn)了 BeanNameAware、BeanClassLoaderAware 或 BeanFactoryAware 接口调卑,回調(diào)
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// BeanPostProcessor 的 postProcessBeforeInitialization 回調(diào)
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 處理 bean 中定義的 init-method抡砂,
// 或者如果 bean 實現(xiàn)了 InitializingBean 接口,調(diào)用 afterPropertiesSet() 方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// BeanPostProcessor 的 postProcessAfterInitialization 回調(diào)
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
6恬涧、之后進行屬性的注入注益,調(diào)用回調(diào)方法,初始化等等溯捆。就是bean生命周期的那幾步丑搔。
先實例化,在注入屬性
如果實現(xiàn)了beanNameAware,beanFactoryAware啤月,ApplicationContextAware煮仇,進行回調(diào)。
如果實現(xiàn)了BeanPostProcessor接口谎仲,調(diào)用PostProcessorsBeforeInitialization方法浙垫。
如果bean中定義了init-method或者實現(xiàn)了InitializingBean 接口,調(diào)用afterPorpertiesSet方法郑诺。
然后再調(diào)用BeanPostProcessor 的 postProcessAfterInitialization 回調(diào)
之后bean就初始化完成了夹姥。可以用了辙诞。
銷毀的話如果實現(xiàn)了DisposableBean接口辙售,調(diào)用destroy方法。如果自定義了destory-method飞涂,也會被調(diào)用圾亏。