Spring 源码剖析IOC容器(一)概览和BeanFactory接口
原创    ren_xian    发表于:2017-10-19 13:35:38
  阅读 :135   收藏   编辑

本文原作者:轩辕流年
本文原链接:http://www.cnblogs.com/dennyzhangdd/p/7652075.html


一、容器概述

spring IOC控制反转,又称为DI依赖注入:大体是先初始化bean再注入使用的过程。本系列默认JDK8源码。容器接口设计图如下:

如上图,可见主要有两条主线

1.基本容器:BeanFactory-》HierarchicalBeanFactory-》ConfigurableBeanFactory

  • BeanFactory接口定义了基本的Ioc容器的规范,包括getBean()这样的Ioc容器的基本方法(通过这个方法可以从容器中取得Bean)。
  • HierarchicalBeanFactory增加了getParentBeanFactory()的接口功能,使BeanFactory具备了双亲Ioc容器的管理功能。
  • ConfigurableBeanFactory定义了一些配置功能,比如通过setParentBeanFactory()设置双亲Ioc容器,通过addBeanPostProcessor()配置Bean后置处理器,等等。

2.高级容器:BeanFactory-》ListableBeanFactory-》ApplicationContext-》WebApplicationContext/ConfigurableApplicationContext

  • ListableBeanFactory细化了许多BeanFactory的接口功能,比如定义了getBeanDefinitionNames()接口方法;
  • ApplicationContext接口,它通过继承MessageSource、ResourcePatternResolver、ApplicationEventPublisher接口,在BeanFactory简单Ioc容器的基础上添加了许多对高级容器的特性支持。

二、核心类源码解读

2.1 BeanFactory接口

尊重源码,以下摘自BeanFactory源码注释翻译:

BeanFactory是获取spring bean容器的顶级接口。该接口被持有一系列bean definitions的对象所实现。依赖bean definitions,工厂返回一个原型实例或者一个单例实例。
通常,BeanFactory将加载存储在配置中的bean definitions资源(例如XML文档)。这些定义没有限制何种方式存储:LDAP, RDBMS, XML,properties file等。并且鼓励使用bean的依赖注入引用。

实现类需要支持Bean的完整生命周期,完整的初始化方法及其标准顺序(格式:接口 方法)为:

1.BeanNameAware setBeanName 设置bean名称
2.BeanClassLoaderAware setBeanClassLoader 设置bean类加载器
3.BeanFactoryAware setBeanFactory 设置bean工厂
4.EnvironmentAware setEnvironment 设置环境:profiles+properties
5.EmbeddedValueResolverAware setEmbeddedValueResolver 设置嵌入式值解析器
6.ResourceLoaderAware setResourceLoader 设置资源载入器,只适用于在应用程序上下文中运行
7.ApplicationEventPublisherAware setApplicationEventPublisher注入应用事件发布器ApplicationEventPublisher
8.MessageSourceAware setMessageSource 设置国际化支持
9.ApplicationContextAware setApplicationContext 设置应用上下文
10.ServletContextAware setServletContext 设置servlet上下文
11.BeanPostProcessors postProcessBeforeInitialization 执行bean处理器前置方法
12.InitializingBean afterPropertiesSet 执行初始化Bean设置完属性后置方法
13.a custom init-method definition 执行自定义初始化方法
14.BeanPostProcessors postProcessAfterInitialization 执行bean处理器后置方法

销毁顺序

1.DestructionAwareBeanPostProcessors postProcessBeforeDestruction 销毁处理器的前置方法
2.DisposableBean destroy Bean销毁回调方法
3.a custom destroy-method definition 用户自定义销毁方法

public interface BeanFactory {

    //转定义符
    String FACTORY_BEAN_PREFIX = "&";

    //定义5种获取Bean方法
    Object getBean(String name) throws BeansException;
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;
    <T> T getBean(Class<T> requiredType) throws BeansException; 
    Object getBean(String name, Object... args) throws BeansException;
    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

    //判断容器是否含有指定名字的Bean
    boolean containsBean(String name);

    //查询指定名字的Bean是否是Singleton类型的Bean.
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    //查询指定名字的Bean是否是Prototype类型的
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

    //查询指定了名字的Bean的Class类型是否是特定的Class类型.
    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

    //查询指定名字的Bean的Class类型.
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;

    //查询指定了名字的Bean的所有别名,这些都是在BeanDefinition中定义的
    String[] getAliases(String name);

}
2.2 XmlBeanFactory实现类

spring3.1之后推荐直接使用:DefaultListableBeanFactory+XmlBeanDefinitionReader(第三节有样例)。虽然这个类已废弃,但不妨碍我们来简单理解一下

@Deprecated
@SuppressWarnings({"serial", "all"})
public class XmlBeanFactory extends DefaultListableBeanFactory {

    private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
    //载入资源构造
    public XmlBeanFactory(Resource resource) throws BeansException {
        this(resource, null);
    }
    //通过载入资源和父类的BeanFactory构造
    public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
        super(parentBeanFactory);
        this.reader.loadBeanDefinitions(resource);
    }

}

1.在XmlBeanFactory中实例化了一个XmlBeanDefinitionReader,这个Reader对象就是用来处理以xml形式的持有类信息的BeanDefinitionl类。

2.BeanDefinitionl信息封装成Resource,作为构造入参

3.调用reader的loadBeanDefinitions,完成容器的初始化和注入。

三、模拟容器获取Bean

public static void main(String[] args) {
        //1.容器IOC获取bean初始化
        ClassPathResource resource = new ClassPathResource("spring.xml");//载入资源
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);//构造reader
        reader.loadBeanDefinitions(resource);//核心方法,解析bean定义
        Dao dao = factory.getBean("daoImpl", Dao.class);//IOC容器DefaultListableBeanFactory通过名称和类class获取bean单例对象
        dao.select();//执行Bean实例方法
}
spring.xml中就写一行:定义一个Bean即可
 <bean id="daoImpl" class="spring.aop.xml.dao.impl.DaoImpl" />

总结:

本文概述IOC原理并分析了核心源码,最后结合一个简单例子,模拟了最简单的容器DefaultListableBeanFactory从xml载入bean定义并生成对象的过程。下一章,我们将分析高级容器ApplicationContext.

=======================

参考

http://www.zzcode.cn/springioc/thread-39.html

评论
条评论