spring-ioc源码分析
概述:spring是一个ioc容器,ioc就是我们把对象之间的依赖关系交给spring进行管理,比如说,我们在配置文件或者java配置类定义了bean的各种关系,spring负责加载这些bean,并维护了类之间的依赖,如果我们需要使用bean,直接getBean即可,这个就是spring作为Ioc容器的主要功能。
一、类介绍
1、ApplicationContext的总览
为了分析ioc的原理,我们先从可以接触到的applicationContent类进行入手,下面这个是我们的启动代码。
ApplicationContext context = new ClassPathXmlApplicationContext(xmlPath)。
以上代码就可以利用配置文件来启动一个 Spring 容器了,这段代码即是从配置文件加载bean到spring容器中,除了ClassPathXmlApplicationContext,我们还有AnnotationConfigApplicationContext(java配置)和FileSystemXmlApplicationContext (和ClassPathXml类似)。
下面我们先看看ApplicationContext的类结构,我们使用过的实现类主要是ClassPathXmlApplicationContext、AnnotationConfigApplicationContext。
ApplicationContext
ConfigurableApplicationContext
AbstractApplicationContext
AbstractRefreshableApplicationContext GenericApplicationContext
AnnotationConfigApplicationContext
AbstractRefreshableConfigApplicationContext
AbstractXmlApplicationContext
ClassPathXmlApplicationContext
2、BeanFactory的介绍
我们在说下BeanFactory这个接口,BeanFactory就是提供bean的接口,它的子接口在这基础上增加了扩展功能,我们上面的ApplicationContext也是实现了BeanFactory接口的,但是真正负责加载bean的是另外一个实现子类DefaultListableBeanFactory完成bean解析注册等工作。 // 可以从AbstractRefreshableConfigApplicationContext内找到DefaultListableBeanFactory类型的属性查看。
ApplicationContext系列也有很多类或接口是实现BeanFactory)
AutowireCapableBeanFactory HierarchicalBeanFactory ListableBeanFactory
ConfigurableListableBeanFactory // 继承了上面三个接口
DefaultListableBeanFactory // 实现了ConfigurableListableBeanFactory 和 BeanDefinitionRegistry (负责注册beanDefinition)
3、BeanDefinition的介绍
在介绍BeanDefinition时,我们知道DefaultListableBeanFactory实现了BeanDefinitionRegistry接口功能用来加载并且注册bean。
我们先看看DefaultListableBeanFactory内部用什么来存储创建的bean,截取部分成员变量,beanDefinitionMap就是存储BeanDefinition信息。
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
BeanDefinition就是保存了我们的bean的名称、bean的类型,依赖那个类,以及是否单例等等信息。
二、流程分析
1、refresh主干方法
ClassPathXmlApplicationContext主要是调用refresh方法,refresh() 方法里面又调用了很多方法,详见下面。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
// 标记1---加载bean配置以及注册
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
// 标记2--- 初始化所有的 singleton beans
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
}
}
}
上面的标记1方法功能表示如何加载BeanDefinition到容器,标记2方法是创建Bean和初始化,其他都是一些附属处理功能。
我们先看看这些附属方法的主要功能:
prepareBeanFactory : 注册默认BeanPostProcessor用来实现一些功能。
invokeBeanFactoryPostProcessors : 执行BeanFactoryPostProcessor的各种实现类的方法。
registerBeanPostProcessors:注册 BeanPostProcessor 的实现类,这个方法会在初始前初始后增强bean,这里还未初始化的。
2、obtainFreshBeanFactory--加载注册bean
介绍完一些refresh的一些公共处理,我们就从refresh的起点方法obtainFreshBeanFactory来看看spring如何把各种bean从配置文件加载到内部的DefaultListableBeanFactory中。
obtainFreshBeanFactory实际调用obtainFreshBeanFactory方法。
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {// ... }
try {
// 创建了DefaultListableBeanFactory,下面设置成this.beanFactory赋值
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
// 实际加载方法
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
}
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
从上面我们可以看到refreshBeanFactory是创建一个DefaultListableBeanFactory来进行加载注册bean。
loadBeanDefinitions 系列调用栈,具体实现过于繁杂,我们知道主要是把配置的bean加载到DefaultListableBeanFactory即可。 (后续补充)
3、finishBeanFactoryInitialization --- 创建bean和初始化bean
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// ....
beanFactory.setTempClassLoader(null);
// 允许缓存元数据,即以后不会变更
beanFactory.freezeConfiguration();
// 实例化所有此时没有实例的单例bean 【主要调用方法】
beanFactory.preInstantiateSingletons();
}
从上面代码可以看到,finishBeanFactoryInitialization实际上是调用DefaultListableBeanFactory的preInstantiateSingletons方法。
public void preInstantiateSingletons() throws BeansException {
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
for (String beanName : beanNames) {
// 得到的BeanDefinition加工成RootBeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 不是抽象方法不是懒加载和多例
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
// ....
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else { // 创建bean的核心方法
getBean(beanName);
}
}
}
// ....略
}
从上面可以看到,只有单例不是懒加载和多例的才会执行到get'Bean方法,并且这个方法调用doGetBean,这个方法超级长。
protected <T> T doGetBean(final String name, final Class<T> requiredType, finalObject[] args, boolean typeCheckOnly)throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// 缓存中取
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// 父工厂取
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException(""); //循环依赖了
}
registerDependentBean(dependsOnBean, beanName);
getBean(dependsOnBean); // 依赖执行注册和getBean
}
}
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
// 创建bean 核心调用方法
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// 多例略....
}
else {
// 其他略....
}
}
}
// ....
return (T) bean;
}
doGetBean方法,经过我的删减还有很长,主要包含从缓存取,如果存在返回,从父容器取,如果找到就返回,然后判断BeanDefinition内部的依赖bean,如果有依赖就注册这个依赖,并且同样执行getBean(),等于递归调用所有依赖的bean,执行一系列的getBean方法。最终,依赖都创建好了,当前Bean开始创建,执行的是createBean方法。实际调用的是doCreateBean。
doCreateBean的代码比较长,只贴主要的。
Object exposedObject = bean;
try {
填充属性
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
初始化,包含BeanPostProcess的前置和后置处理
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 各种awre的执行
invokeAwareMethods(beanName, bean);
if (mbd == null || !mbd.isSynthetic()) {
// 其他BeanPostProcess对本Bean的前置处理
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean,beanName);
}
try {
// 初始化方法执行
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
// ...
}
if (mbd == null || !mbd.isSynthetic()) {
// 其他BeanPostProcess对本Bean的后置处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
从initializeBean方法,我们可以知道,spring一个bean的创建过程的一些Aware、BeanPostProcess、InitMethod等等生命周期的方法都在这个方法中体现了。详见: // spring各种初始化方法大乱斗
至此,spring的IOC相关的代码以及spring容器的主要一些接口类都介绍完了。可以自己写一些例子,结合debug进行断点查看。