spring技术内幕学习笔记01

该来的总会来,spring源码我抵触好几年的东西,总该还了。。。。

1.1 IOC容器的实现

1.1.1 关于DI和IOC

可以说IOC与DI是相互依赖的概念,IOC是指依赖倒置原理,指的是可以在对象生成或初始化的时候直接将数据注入到对象中,也可以通过将对象引用注入到对象数据域中。

1.1.2 BeanFactory与ApplicationContext

这是Spring IOC容器中最重要的两个容器,一般设计线路有两种:

  • 一个是实现Beanfactory接口的简单容器系列
  • 另一个是ApplicationContext应用上下文,它作为高级容器的存在增强了许多面向框架的特性

2.1 IOC容器的设计


这里涉及的是主要接口关系,而具体的IOC容器都是在这个接口体系下实现的,比如DefaultListableBeanFactory,这个基本的容器的实现就是实现了ConfigurableBeanFactory接口从而成为一个简单的IOC容器。
基于这个最基本容器又可以做很多扩展,比如:XmlBeanFactory就是在DefaultListableBeanFactory的基础上做扩展实现的,ApplicationContext的实现也是如此。
关于这个高级容器ApplicationContext可以看到它继承了BeanFactory体系下的ListableBeanFactory和AutowireCapableBeanFactory等接口。具备了BeanFactory的基本功能。在此基础上通过继承MessageSource,ResourceLoadr等接口赋予了更高级的IOC容器特性。

2.1.1 BeanFactory的应用场景

在Spring中BeanFactory只是一个接口类,基于这个接口实现的简单容器譬如:DefaultListableBeanFactory,XmlBeanFactory等等。用户在使用容器的时候可以使用转移符号“&”来得到FactoryBean本身。

关于BeanFactory与FactoryBean前者是一个Bean在Spring中所有的Bean都是由BeanFactory来管理的。而后者是一个工厂,虽然也是一个Bean但是这个Bean不是一个简单的Bean,而是一个能够生产或者修饰对象生成的工厂Bean。

BeanFactory中定义了作为一个IOC容器最基本的功能:

  • Object getBean()
  • boolean containsBean()
  • boolean isSingleton()
  • boolean isPrototype()
  • booolean isTypeMatch()
  • Class getType()
  • String[] getAliases()

2.1.2 BeanFactory的设计原理


XmlBeanFactory继承与DefaultListableBeanFactory,后者非常重要,它是一个我们经常要用到的一个IOC容器的实现,在设计ApplicationContext的时候也会用到这个基类。在Spring中实际上是把DefaultListableBeanFactory作为一个默认的功能完整的Ioc容器来使用的。下面是XmlBeanFactory的源码:

public class XmlBeanFactory extends DefaultListableBeanFactory {

    private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);


    /**
     * Create a new XmlBeanFactory with the given resource,
     * which must be parsable using DOM.
     * @param resource XML resource to load bean definitions from
     * @throws BeansException in case of loading or parsing errors
     */
    public XmlBeanFactory(Resource resource) throws BeansException {
        this(resource, null);
    }

    /**
     * Create a new XmlBeanFactory with the given input stream,
     * which must be parsable using DOM.
     * @param resource XML resource to load bean definitions from
     * @param parentBeanFactory parent bean factory
     * @throws BeansException in case of loading or parsing errors
     */
    public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
        super(parentBeanFactory);
        this.reader.loadBeanDefinitions(resource);
    }

}

创建一个IOC容器的基本步骤:

  1. 创建Ioc配置文件的抽象资源,这个抽象资源包括了BeanDefinition的定义信息
  2. 创建一个BeanFactory工厂一般用的是DefaultListableBeanFactory
  3. 创建一个载入BeanDefinition的读取器,这里使用XmlBeanDefinitionReader来载入XML文件形式的BeanDefinition
  4. 从定义好的资源位置开始载入配置信息。完成整个资源定位,载入,注册这三个步骤后,需要的IOC容器就被建立起来了。

2.1.3 ApplicationContext的应用场景

不同于基于BeanFactory的设计线路,应用上下文多了如下特性:

  • 支持不同的信息源,因为实现了MessageSource接口,这些信息源的扩展功能可以支持国际化的实现
  • 访问资源。由于ResourceLoader和Resource接口的支持,我们可以从不同的地方获取BeanDefinition
  • 支持应用事件

2.1.4 ApplicationContext的设计原理

/**
	 * Create a new FileSystemXmlApplicationContext with the given parent,
	 * loading the definitions from the given XML files.
	 * @param configLocations array of file paths
	 * @param refresh whether to automatically refresh the context,
	 * loading all bean definitions and creating all singletons.
	 * Alternatively, call refresh manually after further configuring the context.
	 * @param parent the parent context
	 * @throws BeansException if context creation failed
	 * @see #refresh()
	 */
	public FileSystemXmlApplicationContext(
		String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {
		super(parent);
		// 设置配置文件集,字符串数组
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
	}

FileSystemXmlApplicationContext继承与基类AbstractXmlApplicationContext。直接创建这样一个IOC容器实列的话会调用IOC容器的启动方法refresh()。

2.2 IOC容器的初始化过程

分为3个主要过程:

  • Resource的定位,指的是BeanDefinition的定位,它由ResourceLoader通过统一的Resource接口来实现。比如文件系统中的BeanDefinition可以用FileSystemResouce来扫描,类路径中的bean信息可以用ClassPathResouce来扫描
  • BeanDefinition信息的载入。具体来说就是将POJO对象中的方法字段抽象到IOC容器中
  • IOC容器注册这些BeanDefinition的过程,这个过程是通过调用BeanDefinitionRegister接口来完成的,在IOC容器内部将这些Bean信息会注入到一个CurrentHashMap中。

Bean的载入和依赖注入是两个不同概念,bean载入不包含实列数据,而依赖注入发生在第一次通过getbean()方法从IOC容器中获取bean的时候。有一个例外就是bean开启了lazy-init那么在IOC容器初始化的时候该bean的依赖注入过程就已经完成了。

posted @ 2021-04-17 18:36  西伯利亚爱学习的狼  阅读(111)  评论(0编辑  收藏  举报