IOC(二)DefaultListableBeanFactory

前言

上一章咱们已经初步认识了BeanFactory和BeanDefinition,一个是IOC的核心工厂接口,一个是IOC的bean定义接口。

spring没法让BeanFactory持有一个Map<String,Object>来完成bean工厂的功能,是由于spring的初始化是能够控制的,能够到用的时候才将bean实例化供开发者使用,除非咱们将bean的lazy-init属性设置为true,初始化bean工厂时采用延迟加载。

那么知道了上述两个接口,我相信很多人甚至不看源码都已经猜到spring是如何作的了。没错,就是让bean工厂持有一个Map<String,BeanDefinition>,这样就能够在任什么时候候咱们想用哪一个bean,取到它的bean定义,咱们就能够创造出一个新的实例。java

接口固然不可能持有这样一个对象,那么这个对象必定是在BeanFactory的某个实现类或者抽象实现类当中所持有的,来看DefaultListableBeanFactory。spring

1、源码分析

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

	private static Class<?> javaUtilOptionalClass = null;

	private static Class<?> javaxInjectProviderClass = null;

	static {
		try {
			javaUtilOptionalClass =
					ClassUtils.forName("java.util.Optional", DefaultListableBeanFactory.class.getClassLoader());
		}
		catch (ClassNotFoundException ex) {
			// Java 8 not available - Optional references simply not supported then.
		}
		try {
			javaxInjectProviderClass =
					ClassUtils.forName("javax.inject.Provider", DefaultListableBeanFactory.class.getClassLoader());
		}
		catch (ClassNotFoundException ex) {
			// JSR-330 API not available - Provider interface simply not supported then.
		}
	}


	/** Map from serialized id to factory instance */
	private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
			new ConcurrentHashMap<String, Reference<DefaultListableBeanFactory>>(8);

	/** Optional id for this factory, for serialization purposes */
	private String serializationId;

	/** Whether to allow re-registration of a different definition with the same name */
	private boolean allowBeanDefinitionOverriding = true;

	/** Whether to allow eager class loading even for lazy-init beans */
	private boolean allowEagerClassLoading = true;

	/** Optional OrderComparator for dependency Lists and arrays */
	private Comparator<Object> dependencyComparator;

	/** Resolver to use for checking if a bean definition is an autowire candidate */
	private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();

	/** Map from dependency type to corresponding autowired value */
	private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<Class<?>, Object>(16);

	/** Map of bean definition objects, keyed by bean name */
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);

	/** Map of singleton and non-singleton bean names, keyed by dependency type */
	private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);

	/** Map of singleton-only bean names, keyed by dependency type */
	private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);

	/** List of bean definition names, in registration order */
	private volatile List<String> beanDefinitionNames = new ArrayList<String>(256);

	/** List of names of manually registered singletons, in registration order */
	private volatile Set<String> manualSingletonNames = new LinkedHashSet<String>(16);

	/** Cached array of bean definition names in case of frozen configuration */
	private volatile String[] frozenBeanDefinitionNames;

	/** Whether bean definition metadata may be cached for all beans */
	private volatile boolean configurationFrozen = false;复制代码
该类的属性就在这里了,至于方法此处被我省略,由于太长了...

看它名字就知道,这是一个默认的bean工厂实现类,根据类注释能够知道这是一个完整的,成熟的IOC容器。也就是说,若是你须要的功能很是单一,这个实现类已经足够能够知足你了,而之后若是你想要对spring的容器扩展,那么只须要扩展或者持有这个对象便可。

/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);复制代码
看到这一行,其实已经证实了个人猜想,它所注释的意思是bean定义的map对象,采用beanName做为key值。

只继承了一个抽象类,同时把集大成的接口ConfigurableListableBeanFactory给实现了,同时还有BeanDefinitionRegistry接口,从名字上看就知道是BeanDefinition的注册接口。

看到这里,思路已经很明确了,bean工厂的初始化其实就是往这个Map里填充东西。只要把咱们XML文件中定义的bean都填充到这里,其实这个工厂就已经能够工做了。

那么从如今来看,咱们须要什么才能把Map填充呢?也就是初始化bean工厂呢,或者说创建IOC容器。

2、IOC容器实现原理讨论

此次先不关注源码,先首先看看它的用法。

ClassPathResource res=new ClassPathResource("beans.xml");
DefaultListableBeanFactory factory=new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader=new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(res);
Performer performer=(Performer) factory.getBean("dancer");
performer.perform();复制代码
简单解释一下:
1.咱们在beans.xml中定义了一个Bean,id为“dancer”,实现了Performer接口。参考自<Spring in action>例子.
2.利用Resource抽象实现类,来包装这个包含了BeanDefinition的定义信息。
3.建立一个BeanFactory,DefaultListableBeanFactory
4.建立一个载入BeanDefinition的读取器,经过回调配置给BeanFactory.
5. 从定义好的Resource中,读取配置信息。由XmlBeanDefinitionReader完成解析,完成整个载入和注册Bean定义的过程。
6. 经过BeanFactory的getBean()方法,获取对应的Bean。这里涉及到了Bean的实例化以及依赖注入

依赖注入的过程

以上过程能够当作是IOC容器初始化的过程,这个初始化过程完成的主要工做是完成BeanDefinition在IOC容器中的数据映射。而这里并无实例化任何对象,也历来没有完成过依赖注入的过程。

依赖注入是经过getBean方法完成的,固然若是将lazy-init属性设置为true,则能够在初始化的过程当中完成依赖注入,实现预实例化。缓存

Performer performer=(Performer) factory.getBean("dancer");经过getBean得到名为“dancer”的对象,而factory如今保有的仅仅是键为“dancer”的BeanDefinition对象(保存在Map中)。ide

而经过源码能够发现getbean()方法是由AbstractBeanFactory实现的,而具体实现又跳到了doGetBean()方法,源码分析

doGetBean()方法负责从Bean工厂中获取bean对象的具体实现,下面来看看该方法的具体实现:this

  1. 检查手动注册的单例集合缓存中是否含有该bean对象,如有,则取出返回,不然继续执行;
  2. 检查该bean是否已经建立,从而判断是否属于循环引用,如果,抛出异常返回,不然继续执行;
  3. 判断bean工厂中是否存在该bean definition,若存在,则取出返回,不然继续执行;
  4. 初始化该bean所依赖的bean对象;
  5. 判断该bean是不是单例模式(singleton),如果,建立单例对象,不然继续执行;
  6. 判断该bean是不是原型模式(prototype),如果,建立原型对象,不然继续执行;
  7. 建立自定义类型(scope)bean对象。
  8. 从上面对doGetBean方法分析,可看出建立并获取bean对象是一个很是复杂的过程,并非简简单单的放入Map中再从其中取出。

3、小结

      整篇文章下来,能够看到DefaultListableBeanFactory实现了IOC容器的初始化而且经过getbean()完成了依赖注入。整个IOC容器初始化过程总结起来就是定位(定位到配置文件)、解析(解析配置文件,通常是XML)、注册(将读出来的数据放到map中)。
      这篇文章里我并无仔细记录源码的执行过程,由于内容实在是太多,我只是经过一个demo讲述了DefaultListableBeanFactory获取一个bean的大概过程。具体源码执行过程还须要各位读者本身去探索,我也是本身经过源码把这个过程探索了一遍才知道IOC容器初始化的过程,不过其中有些地方尚未彻底领悟,待本身有所提高后再回来看看应该会有不同的感觉。


依赖注入过程参考自
相关文章
相关标签/搜索