在spring容器中,BeanDefinition是最为重要的元素。那么从我们配置的xml到最终成为被容器管理的bean最起码要经过以下几个过程
第一、资源定位。spring能够定位到我们配置的文件。通常,我们把配置信息放置到xml文件中去,spring要根据自己的规则找到配置文件。
第一、文件解析,将我们配置到xml或者其他文件中的类元素转化成为可以被spring容器认识的元素-beanDefinition
第二、beanDefinition的载入。有了beanDefinition还要将其转化成Spring内幕标示的数据结构。这个结构IOC容器通过HashMap去维护。
FileSystemXmlApplicationContext是bean载入的成熟上下文。他的整个过程包括了bean从配置文件元素,到能够被spring容器管理的所有过程。
FileSystemXmlApplicationContext
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
AbstractApplicationContext
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) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
refresh方法里面又包含了12个方法。这12个方法包括了IOC容器启动所有的内容。接下来让我们一个一个看看每个方法都做了什么
1、 // Prepare this context for refreshing.
prepareRefresh();第一个方法的注释写着为重新启动上下文做准备。也就是说这个方法 主要做了准备工作。准备工作都包括了什么呢?
protected void prepareRefresh() {
// Initialize any placeholder property sources in the context environment//初始化所有在上下文环境中的占位符属性元
initPropertySources();
// Validate that all properties marked as required are resolvable
// see ConfigurablePropertyResolver#setRequiredProperties//验证所有标示为required的属性被正确的设置。
getEnvironment().validateRequiredProperties();
}
prepareRefresh方法首先将项目的上下文环境都放置进来了。包括war包位置、临时文件位置、占位符、server等等信息。然后通过调用validateRequiredProperties()方法判断requiredProperties里面的属性是否正确的设置进来了。在我的项目中,requiredProperties是空。没有做任何操作。
2、告诉子类刷新内部的bean factory类
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
该方法首先调用refreshBeanFactory()做了以下几个动作:
1、判断beanFactory是否非空,非空则清空bean容器、清空缓存、清空beanFactory。
2、创建DefaultListableBeanFactory实例。这个过程设置了父子容器的关系。
3、设置上文实例化的DefaultListableBeanFactory的内部属性。包括设置candidate resolver ,该属性决定该bean Definition是否被认为能够autowiring。
4、为指定的bean工厂加载了bean。实际加载bean的是XmlBeanDefinitionReader 实例。接下来初始化reader和加载bean过程由相应的子类实现。
我们系统中配置的xml信息最终都已Resouces类的形式被spring读取。
reader.loadBeanDefinitions(configLocations);方法将我们配置的spring xml文件信息解析出来。。
解析进来要包括我们配置的方方面面。包括像autowired属性,各个bean的property属性。这些都是使用reader"笔"来载入的。
最终,将beanDefinitions放置到了beanDefinitionMap中。
3、工厂类有了,接下来就是如何让这个工厂类配置信息,让他有容器工厂的样子。配置工厂的标准上下文特性,比如上下文的类加载器和后置处理器等等。 prepareBeanFactory(beanFactory);
除了设置一些关于容器的类信息之外。最重要的就注册进来新的类到容器中。这三个类包含了jdk、servlet容器的信息都在这一步设置进了容器中。
4、 这个过程主要包括后置处理器设置、作用域设置。包括web.xml里面设置的xml文件位置解析postProcessBeanFactory(beanFactory);
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { .
五、触发后置处理器。
步骤4已经将后置处理器注册到了工厂类中,接下来就是出发这些工厂类的时候了。
1、从工厂类中获取到后置处理器
2、后置处理器有优先级。我们要对处理器的前后顺序排序
3、如果没有在工厂类中获取后置处理器,那从工厂加载的bean中寻找后置处理器。触发这些后置处理器。
invokeBeanFactoryPostProcessors(beanFactory);
六、注册拦截bean创建的 bean处理器 registerBeanPostProcessors(beanFactory);
1、获取到后置处理器(包括三个类型)
2、将后置处理器增加到了factory中(包括一个监听器后置处理器ApplicationListenerDetector)
七、 初始化上下文的消息资源
initMessageSource();
在factory中注册了一个名称为MESSAGE_SOURCE_BEAN_NAME的类。
如果配置了,则从容器中获取到bean。
如果没有配置,则采用默认的方式创建,将其将其添加到singletonObjects中。
八、初始化上下文的事件广播。 initApplicationEventMulticaster();
在factory中注册一个名为APPLICATION_EVENT_MULTICASTER_BEAN_NAME的类。如果factory中已经有名称为APPLICATION_EVENT_MULTICASTER_BEAN_NAME的类,则从容器中获取到bean。
如果没有配置,则采用默认的方式创建,将其添加到 singletonObjects中。
// Initialize other special beans in specific context subclasses.
九、初始化铁定上下文子类中其他特殊的bean。
子类中都通过它增加了主题功能的支持。 onRefresh();
protected void onRefresh() {
this.themeSource = UiApplicationContextUtils.initThemeSource(this);
} // Check for listener beans and register them.
十、查找监听bean,并注册他们。 registerListeners();
//获取到上下文中的监听,将其添加到SimpleApplicationEventMulticaster类的监听器列表中
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
//获取到注册进来的bean中类型为ApplicationListener的监听器,将其添加到SimpleApplicationEventMulticaster类的监听器列表中。 String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String lisName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(lisName);
}
}
十一、实例化所有剩余类型为单利的bean finishBeanFactoryInitialization(beanFactory);
包括以下几个步骤:
1、判断类型为CONVERSION_SERVICE_BEAN_NAME类是否存在,存在则将其设置进工厂类中。
2、判断类型为LoadTimeWeaverAware的类是否存在,依赖注入之。
3、取消掉临时类加载器。
4、设置缓存frozenBeanDefinitionNames
5、初始化剩余的非懒加载的单例类。
十二、发布事件。
finishRefresh();
1、初始化一个类:org.springframework.context.support.DefaultLifecycleProcessor
首先判断factory中是否包含名称为lifecycleProcessor的类,如果有则将其赋值给上下文的lifecycleProcessor中。如果没有则将实例化一个默认值DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();并将其复制给上下文的lifecycleProcessor中
2
2.1、获取容器中加载进来的类中哪个类是Lifecycle.class类型的。
2.2、将Lifecycle.class类型的类放置到容器中返回。
2.3、启动监听容器。
3、
3.1、获取线程池线程
3.2、调用监听方法listener.onApplicationEvent(event),执行监听事件。上文中说@Scheduled方法的时间就是在这个时候出发执行的。
4、没用过,不懂。官方的注解是在LiveBeansView MBean环境中使用。