为了账号安全,请及时绑定邮箱和手机立即绑定

Spring Ioc 源码分析(一)--Spring Ioc容器的加载

标签:
Java

1.目标:熟练使用spring,并分析其源码,了解其中的思想。这篇主要介绍spring ioc 容器的加载
2.前提条件:会使用debug
3.源码分析方法:Intellj idea debug 模式下源码追溯
通过ClassPathXmlApplicationContext 进行xml 件的读取,从每个堆栈中读取程序的运行信息
加粗文字4.注意:由于Spring的类继承体系比较复杂,不能全部贴图,所以只将分析源码之后发现的最主要的类继承结构类图贴在下方。
5.关于Spring Ioc Demo:**我们从demo入手一步步进行代码追溯。

1.Spring Ioc Demo

1.定义数据访问接口IUserDao.java

public interface IUserDao {  
public void InsertUser(String username,String password);
}

2.定义IUserDao.java实现类IUserDaoImpl.java

public class UserDaoImpl implements IUserDao {    
@Override    
public void InsertUser(String username, String password) { 
System.out.println("----UserDaoImpl --addUser----");    
}
}

3.定义业务逻辑接口UserService.java

public interface UserService {    
public void addUser(String username,String password);
}

4.定义UserService.java实现类UserServiceImpl.java

public class UserServiceImpl implements UserService {    
private     IUserDao  userDao;    //set方法  
public void  setUserDao(IUserDao  userDao) {        
this.userDao = userDao;   
}    
@Override    
public void addUser(String username,String password) { 
userDao.InsertUser(username,password);    
}
}

bean.xml配置文件

<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-3.0.xsd         ">  
<!--id名字自己取,class表示他代表的类,如果在包里的话需要加上包名-->    
<bean id="userService"  class="UserServiceImpl" >      
<!--property代表是通过set方法注入,ref的值表示注入的内容-->
<property  name="userDao"  ref="userDao"/>  
</bean>    
<bean id="userDao"  class="UserDaoImpl"/>
</beans>
2.ApplicationContext 继承结构:

1.顶层接口:ApplicationContext
2.ClassPathXmlApplicationContext实现类继承AbstractXmlApplication 抽象类
3.AbstractXmlApplication 继承AbstractRefreshableConfigApplicationContext
4.AbstractRefreshableConfigApplicationContext抽象类继承AbstractRefreshableApplicationContext
5.AbstractRefreshableApplicationContext 继承 AbstractApplicationContext
6.AbstractApplicationContext 实现ConfigurableApplicationContext 接口
7.ConfigurableApplicationContext 接口继承
ApplicationContext接口
总体来说继承实现结构较深,内部使用了大量适配器模式。
以ClassPathXmlApplicationContext为例,继承类图如下图所示:
Spring

3.Spring Ioc容器加载过程源码详解

在开始之前,先介绍一个整体的概念。即spring ioc容器的加载,大体上经过以下几个过程:
资源文件定位、解析、注册、实例化
1.资源文件定位
其中资源文件定位,一般是在ApplicationContext的实现类里完成的,因为ApplicationContext接口继承ResourcePatternResolver 接口,ResourcePatternResolver接口继承ResourceLoader接口,ResourceLoader其中的getResource()方法,可以将外部的资源,读取为Resource类。
2.解析DefaultBeanDefinitionDocumentReader
解析主要是在BeanDefinitionReader中完成的,最常用的实现类是XmlBeanDefinitionReader,其中的loadBeanDefinitions()方法,负责读取Resource,并完成后续的步骤。ApplicationContext完成资源文件定位之后,是将解析工作委托给XmlBeanDefinitionReader来完成的
解析这里涉及到很多步骤,最常见的情况,资源文件来自一个XML配置文件。首先是BeanDefinitionReader,将XML文件读取成w3c的Document文档。
DefaultBeanDefinitionDocumentReader对Document进行进一步解析。然后DefaultBeanDefinitionDocumentReader又委托给BeanDefinitionParserDelegate进行解析。如果是标准的xml namespace元素,会在Delegate内部完成解析,如果是非标准的xml namespace元素,则会委托合适的NamespaceHandler进行解析最终解析的结果都封装为BeanDefinitionHolder,至此解析就算完成。
后续会进行细致讲解。


3.注册
然后bean的注册是在BeanFactory里完成的,BeanFactory接口最常见的一个实现类是DefaultListableBeanFactory,它实现了BeanDefinitionRegistry接口,所以其中的registerBeanDefinition()方法,可以对BeanDefinition进行注册这里附带一提,最常见的XmlWebApplicationContext不是自己持有BeanDefinition的,它继承自AbstractRefreshableApplicationContext,其持有一个DefaultListableBeanFactory的字段,就是用它来保存BeanDefinition
所谓的注册,其实就是将BeanDefinition的name和实例,保存到一个Map中。刚才说到,最常用的实现DefaultListableBeanFactory,其中的字段就是beanDefinitionMap,是一个ConcurrentHashMap。
代码如下:
1.DefaultListableBeanFactory继承实现关系

public class DefaultListableBeanFactory
 extends 
 AbstractAutowireCapableBeanFactory   
 implements
 ConfigurableListableBeanFactory, 
 BeanDefinitionRegistry,
 Serializable { 
      // DefaultListableBeanFactory的实例中最终保存了所有注册的bean    beanDefinitionMap
      /** Map of bean definition objects, keyed by bean name */
      private final Map<String, BeanDefinition> beanDefinitionMap 
      = new ConcurrentHashMap<String, BeanDefinition>(64); 
      //实现BeanDefinitionRegistry中定义的registerBeanDefinition()抽象方法
      public void registerBeanDefinition(String beanName, BeanDefinition    beanDefinition)      throws BeanDefinitionStoreException {
      }

2.BeanDefinitionRegistry接口
```public interface BeanDefinitionRegistry extends AliasRegistry {
//定义注册BeanDefinition实例的抽象方法
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;


**4.实例化**
****
注册也完成之后,在BeanFactory的getBean()方法之中,会完成初始化,也就是依赖注入的过程
大体上的流程就是这样,下一篇博客,再具体地从代码层面进行介绍。
点击查看更多内容
8人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消