目录
前言
从本篇开始介绍Spring源码相关内容,Spring的源码博大精深,值得终身学习,后面的一些博客可以说是自己总结。
spring启动有两种方式:xml方式和注解的方式,这两种方式入口类的UML图如下:
一、xml代码
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="order" class="com.example.beans.Orders">
<property name="id" value="1234"/>
<property name="username" value="xuxb"/>
</bean>
</beans>
public class SpringAppXml {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
System.out.println(applicationContext.getBean("order"));
}
}
二、注解方式
@Configuration
public class WAppConfig {
@Bean
public Orders myOrders() {
return new Orders();
}
}
public class WApp {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext("com.worker");
Orders order = context.getBean("orders", Orders.class);
System.out.println(order.toString());
}
}
三、执行流程
通过上面流程图可知,这两种方式最终会执行refresh,后面在分析refresh方法
3.1、xml核心源码
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations); //spring的配置文件例如spring.xml
if (refresh) {//刷新
refresh();
}
}
3.2、注解方式
public AnnotationConfigApplicationContext(String... basePackages) {
this();
scan(basePackages); //包扫描 注册bean definitions
refresh(); //AbstractApplicationContext refresh
}
四、refresh方法
refresh是核心方法,当refresh方法执行完毕后,spring应用就完成。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
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.
// 注册一些系统bean和beanPostProcessor
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// web应用会处理一些内容,但spring应用是空方法
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.
// 实例化在子类context中定义的bean对象
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 初始化单例bean,非懒加载bean
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();
contextRefresh.end();
}
}
}
spring其实已经加了很多注释非常全面,但是对于新手来说,在不了解spring的各种场景下,这些注释作用其实并不大。
五、总结
后面我计划写这些内容:1、BeanDefinition,2、Bean生命周期(三级缓存),3、Bean查找,4、配置文件解析,5、常用注解分析