参考:https://javadoop.com/post/spring-ioc#customizeBeanFactory
https://javadoop.com/blogimages/spring-context/2.png
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,然后调用他的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还没有结束的时候又去启动或者销毁容器。
@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、之后注册一些回调,一些监听器,和一些钩子方法用来扩展
// 初始化所有的 singleton beans
//(lazy-init 的除外)
finishBeanFactoryInitialization(beanFactory);
5、调用finishBeanFactoryInitaization实例化bean
先进行实例化,如果不存在方法覆写,那么就使用反射进行实例化,否则使用CGLIB。如果有需要覆盖或者动态替换的方法使用Cglib进行动态代理,如果没有需要动态改变的方法那就直接使用反射进行实例化。所谓的动态替换或覆盖的情况,就是使用了replace或者lookup的配置方法。这两个方法的作用就是在调用目标方法的时候,对调用过程进行拦截,调用实现增强功能的拦截器,返回原来实例的代理。
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 实现了 BeanNameAware、BeanClassLoaderAware 或 BeanFactoryAware 接口,回调
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// BeanPostProcessor 的 postProcessBeforeInitialization 回调
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 处理 bean 中定义的 init-method,
// 或者如果 bean 实现了 InitializingBean 接口,调用 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 回调
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
6、之后进行属性的注入,调用回调方法,初始化等等。就是bean生命周期的那几步。
先实例化,在注入属性
如果实现了beanNameAware,beanFactoryAware,ApplicationContextAware,进行回调。
如果实现了BeanPostProcessor接口,调用PostProcessorsBeforeInitialization方法。
如果bean中定义了init-method或者实现了InitializingBean 接口,调用afterPorpertiesSet方法。
然后再调用BeanPostProcessor 的 postProcessAfterInitialization 回调
之后bean就初始化完成了。可以用了。
销毁的话如果实现了DisposableBean接口,调用destroy方法。如果自定义了destory-method,也会被调用。
网友评论