SpringIOC源码走读
- 简介
- 准备工作
- 阅读源码
- super(parent);
- setConfigLocations(configLocations);
- refresh();
- prepareRefresh()
- obtainFreshBeanFactory()
- prepareBeanFactory(beanFactory)
- postProcessBeanFactory(beanFactory)
- invokeBeanFactoryPostProcessors(beanFactory)
- registerBeanPostProcessors(beanFactory)
- initMessageSource()
- initApplicationEventMulticaster()
- onRefresh()
- registerListeners()
- finishBeanFactoryInitialization(beanFactory)
- finishRefresh()
- 总结
简介
Spring的两大核心就是IOC和AOP,了解其机制可以有效的提高我们对于spring的理解和运用。本篇文章我们先来了解一下Spring IOC的大致实现过程。
准备工作
Spring的常用方式包括XML配置和java配置两种方法,本篇文章我们使用xml配置的方式来了解Spring IOC的机制。
- 引入spring依赖 ,这个就不写了;
- 编写一个java类用于等下注入到spring;
public class Animal {
private String name;
private int sex;
//...省去get/set和toString
}
- 在resource目录下添加一个applicationContext.xml并注入Animal;
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="animal" class="com.liyanan.springmvc.Animal">
<property name="name" value="tiger"/>
<property name="sex" value="0"/>
</bean>
</beans>
- 编写测试类获取animal,并打印出animal的信息;
public class AnimalTest {
@Test
public void testIoc() {
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
Animal animal = applicationContext.getBean(Animal.class);
System.out.println(animal);
}
}
阅读源码
准备工作做完了,现在可以开始跟着debug阅读源码了。
从上面可以知道入口在new ClassPathXmlApplicationContext(“classpath:applicationContext.xml”)中,点进去最终调用如下:
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
super(parent);
没什么太大的作用,设置一下父级ApplicationContext,这里是null。
setConfigLocations(configLocations);
将配置文件路径保存到configLocations中。
refresh();
这个就是整个Spring Bean加载的核心了,它是ClassPathXmlApplicationContext的父类AbstractApplicationContext的一个方法,顾名思义,用于刷新整个Spring上下文信息,定义了整个Spring上下文加载的流程。
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();
}
prepareRefresh()
initPropertySources();初始化placeholder资源占位符里面的资源。
验证所有必须的properties是否可解析。
初始化earlyApplicationEvents。
obtainFreshBeanFactory()
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
@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);
}
}
destroyBeans()和closeBeanFactory()的作用是销毁之前的数据,并重新创建DefaultListableBeanFactory工厂,配置是否支持bean定义重写allowBeanDefinitionOverriding和循环引用allowCircularReferences,默认都是true。
loadBeanDefinitions(beanFactory)加载beanDefinitions,在DefaultBeanDefinitionDocumentReader的doRegisterBeanDefinitions中读取xml中beans节点下的内容。
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
最终调用DefaultListableBeanFactory.registerBeanDefinition()方法,把bean的名字和定义以键值对的形式保存到DefaultListableBeanFactory的beanDefinitionMap中。
XML解析:
AbstractXmlApplicationContext#loadBeanDefinitions方法
1.创建XmlBeanDefinitionReader,构造把DefaultListableBeanFactory作为register传入
2.调用loadBeanDefinitions(beanDefinitionReader)
调用AbstractBeanDefinitionReader的loadBeanDefinitions()方法
调用XmlBeanDefinitionReader的loadBeanDefinitions(EncodedResource encodedResource)方法
调用doLoadBeanDefinitions()方法根据资源文件创建Document对象
调用registerBeanDefinitions(Document doc, Resource resource)注册bean定义
创建DefaultBeanDefinitionDocumentReader对象
调用DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root)方法,参数为上面的Document对象获取的Element
preProcessXml(root),预处理Xml,在ClassPathXmlApplicationContext的步骤中这里是个空实现
parseBeanDefinitions(root, this.delegate)
在parseDefaultElement()中解析beans,bean,import,alias四个标签,在解析bean的时候获取获取bean里面的attr等属性用于反射装载对象
在BeanDefinitionParserDelegate.java的parseBeanDefinitionElement()中解析bean元素具体属性
bean里面的属性的解析主要在BeanDefinitionParserDelegate.java的parseBeanDefinitionAttributes()里面
从属性值的获取里面可以知道一个bean可以添加哪些属性,比如init-method,destroy-method等等。
bean的构造等等也是在BeanDefinitionParserDelegate.java的parseConstructorArgElements()中等等。。
prepareBeanFactory(beanFactory)
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
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.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
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());
}
}
1: 设置classloader
2: 设置Spel表达式解析器
3: 添加特定后置处理器
4: 存储不自动装配的接口Class对象集合,在DefaultListableBeanFactory的父类里面
5: 将一些bean以键值对的形式保存到DefaultListableBeanFactory的resolvableDependencies中注册依赖当注册了依赖解析后,例如当注册了对BeanFactory.class的解析后,当bean的属性注入的时候,一旦检测到属性为BeanFactory类型便会将beanFactory的实例注入进去。
6: 注册特定后置处理器
7: 注册系统相关属性bean
postProcessBeanFactory(beanFactory)
在ClassPathXmlApplicationContext的继承关系里,这里是个空实现。
invokeBeanFactoryPostProcessors(beanFactory)
实例化并且调用所有的BeanFactoryPostProcessor bean工厂后置处理器,如果有指定优先级,会按照优先级进行实例化(就是继承类似PriorityOrdered和Order的接口的BeanFactoryPostProcessor)并调用他们的postProcessBeanDefinitionRegistry。
这个具体是实现在org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()里面,因为代码太长就不贴了。
registerBeanPostProcessors(beanFactory)
把BeanPostProcessor bean后置处理器保存到DefaultListableBeanFactory的父类AbstractBeanFactory的beanPostProcessors中,并调用processor的方法具体是在PostProcessorRegistrationDelegate.registerBeanPostProcessors()方法中registerBeanPostProcessors()BeanProcessor的添加按照是否实现了PriorityOrdered,Ordered和普通的顺序。
(所以),我们只需要在配置文件中添加我们自定义的BeanPostProcessor,在前面的obtainFreshBeanFactory()会将我们的后置处理器添加到DefaultListableBeanFactory中。
然后在这里将beanfactory中读取出来的后置处理器添加到DefaultListableBeanFactory的beanPostProcessors集合中。
initMessageSource()
这个是加载跟i18n相关的配置。
initApplicationEventMulticaster()
注册ApplicationEventMulticaster。
onRefresh()
在当前过程中也是一个空实现。
registerListeners()
protected void registerListeners() {
for (ApplicationListener<?> listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener);
}
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
注册所有的ApplicationListener。
(所以) :我们可以在xml中配置我们自定义的ApplicationListener用于监听我们想要监听的事件根据ApplicationListener的泛型描述 the specific ApplicationEvent subclass to listen to我们可以知道想要监听具体的ApplicationEvent,只需要指定相应的泛型即可。
finishBeanFactoryInitialization(beanFactory)
实例化所有的非懒加载单例bean,并在执行init-method前后调用BeanPostProcessor后置处理器的两个方法具体在AbstractAutowireCapableBeanFactory.initializeBean()中。
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 {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
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()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
finishRefresh()
容器加载完成,并且通知所有的ApplicationListener该完成事件。
总结
基于Xml配置的SpringIOC的主要流程在于AbstractApplicationContext和DefaultListableBeanFactory。
AbstractApplicationContext主要处理Spring容器刷新的过程,包括创建beanfactory,解析bean,配置后置处理器,配置PlaceHolder资源解析器等等。
DefaultListableBeanFactory主要是保存几乎所有的bean和他的beandefinition以及后置处理器等等,算是真正的容器所在。而且我们可以在配置文件中自定义BeanPostProcessor,ApplicationListener等等。