Spring IOC之BeanFactory

      做过不少项目,用到最多的框架当属 Spring 了,但是至今都没有去整理过任何一篇关于 Spring 学习的文档:一是因为 Reference 比较详细,平时项目中基本上都能查到;二是因为有很多关于 Spring 的文章都写的相当好,觉得没有必要自己再写。今天我鼓起勇气整理一篇关于 BeanFactory 相关的文章,算是自己对 Spring Ioc 学习的一归纳,学习笔记嘛,否则,读过代码在记忆停留的时间总是那么有限。

    BeanFactory ,作为 Spring 基础的 IoC 容器,从名字上看就是 Spring 的一个 Bean 工厂。如果单从工厂模式的角度思考,它就是用来“生产 Bean ”,然后提供给客户端。但是它到底是如何生产 Bean 的呢?生产 Bean 的“原料”获取、解析、以及 Bean 之间的依赖是如何完成的呢?这并不没有想象中的那么简单。直接来看最基础的 BeanFactory 类图吧:
Spring IOC之BeanFactory

     在细看类图之前,先弄清 IOC 的流程。回想我们平时使用,大多数时候只是配置一下,就可以直接使用 Spring IOC 了,这其中必然需要读取配置、解析配置、生产 Bean 、将 Bean 注册到一个统一的地方提供客户端获取使用。暂不考虑配置的读取和解析,来看 spring 的接口功能的定义:

 

1.          首先是顶层的 BeanFactory ,从他定义的方法看,主要提供获 Bean 对象,判断给定的 Bean 对象是否被当前的 BeanFactory 加载过、是否是 Singleton/Prototype 、类型是否匹配,等等最最基本,也是客户端最最需要使用的功能 ( 如果不是为了学习,客户端才不会关心你的 bean 是怎么来的,反正我只要能调用完成自己的功能就 ok )

2.        左边分支:也就是 ListableBeanfactory ,此接口继承了 BeanFactory 的同时,提供了列举 Bean 的功能,他能够列举当前 BeanFactory 加载的所有 Bean :列举所有 Bean 的名字或者满足某种类型的 Bean 的名字,根据类型返回所有 Bean 对象 , 等。但是它无法获取上层 BeanFactory 加载的单例 Bean

3.        看中间分支: HierachicalBeanFactory ConfigurableBeanFactory HierarchicalBeanFactory 比较简单,它主要是提供父 BeanFactory 的功能,通过它能够获取当前 BeanFactory 的父工厂( PS: 若在 A 工厂启动并加载 Bean 之前, B 工厂先启动并加载了,那 B 就是 A 的父工厂),这样就能让当前的 BeanFactory 加载父工厂加载的 Bean 了,弥补了 ListableBeanfactory 欠缺的功能。 ConfigurableBeanFactory 就是在 HierarchicalBeanFactory 的基础上增加了可配置的功能,包括注册别名、注册单例等,设置 Classloader 、是否缓存 Bean Metadata 、设置 TypeConverter BeanPostProcessor 、配置 Bean 依赖等。 PS:ConfigurableBeanFactory 还继承了 SingletonBeanRegistry 接口主要是用来定义为用来共享的 bean 实例的注册表,通过它可以使得 BeanFactory 实现统一的方式暴露其单例 bean 管理。

4.        再看右边分支:该分支分两块――

      首先是 AutowireCapableBeanFactory ,主要是提供自动 Bean 自动绑定 ( 或者说自动装配 ) 功能。例如根据自动装配策略 new 一个 bean ,为已有的 bean 装配属性依赖;还有创建 bean 之后的回调功能,为 bean 设置 name bean factory bean post processor 等;将 bean post processor 应用到 bean 的初始化,等等。    其次 SingletonBeanRegistry/DefaultSingletonBeanRegistry/FactoryBeanRegistrySupport SingletonBeanRegistry 在前面已提到, DefaultSingletonBeanRegistry 是它的默认实现类,它不仅支持 Singleton Bean 的注册,也支持 DisposableBean 的注册管理用来清理要丢弃的 bean 以及他们依赖的资源。如果去大概看一下代码的话,它主要维护了这些资源:

 

 

/** Cache of singleton objects: bean name --> bean instance */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>();

	/** Cache of singleton factories: bean name --> ObjectFactory */
	private final Map<String, ObjectFactory> singletonFactories = new HashMap<String, ObjectFactory>();

	/** Cache of early singleton objects: bean name --> bean instance */
	private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>();

	/** Set of registered singletons, containing the bean names in registration order */
	private final Set<String> registeredSingletons = new LinkedHashSet<String>(16);

	/** Names of beans that are currently in creation */
	private final Set<String> singletonsCurrentlyInCreation = Collections.synchronizedSet(new HashSet<String>());

	/** List of suppressed Exceptions, available for associating related causes */
	private Set<Exception> suppressedExceptions;

	/** Flag that indicates whether we're currently within destroySingletons */
	private boolean singletonsCurrentlyInDestruction = false;

	/** Disposable bean instances: bean name --> disposable instance */
	private final Map<String, Object> disposableBeans = new LinkedHashMap<String, Object>();

	/** Map between containing bean names: bean name --> Set of bean names that the bean contains */
	private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<String, Set<String>>();

	/** Map between dependent bean names: bean name --> Set of dependent bean names */
	private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<String, Set<String>>();

	/** Map between depending bean names: bean name --> Set of bean names for the bean's dependencies */
	private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<String, Set<String>>();

 

    仔细读一下代码的话,可以看到 Spring 对这些容器的并发、同步的控制,这些都依赖与 Spring Core 以及 JDK

    再说 FactoryBeanRegistrySupport ,主要是对 FactoryBean 的支持, 获取 FactoryBean FactoryBean 的类型、获取 FactoryBean 曝露的目标对象等,而这些功能都是基于附接口对 Bean 的注册功能的。 FactoryBean Spring 提供的一种扩展容器实例化 Bean 逻辑的接口,相信大家都用过类似 ProxyFactoryBean TransactionProxyFactoryBean LocalSessionFactoryBean 等,其实 Spring 和其框架整合的时候都会针对具体框架提供一个 ***FactoryBean 。而 AbstractBeanFactory 既实现了 ConfigurableBeanFactory ,又继承了 FactoryBeanRegistrySupport 的功能。

    最后 AbstractAutoWireCapableBeanFactory ,实现 AutowireCapableBeanFactory 接口的 Bean 装配功能,可参见其实现的 createBean/autowireBean/configureBean 方法,这里就包含了 bean 创建装配的逻辑。以最完整的 createBean 方法为例,来窥探下整个流程:概括的讲先根据 Class 类型包装成 RootBeanDefinition 并设置 SCOPE ,然后调用重载方法 createBean(beanClass.getName(), bd, null) 就完事了。 看这个重载方法:

 

protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
			throws BeanCreationException {

		AccessControlContext acc = AccessController.getContext();
		return AccessController.doPrivileged(new PrivilegedAction() {
			public Object run() {
				if (logger.isDebugEnabled()) {
					logger.debug("Creating instance of bean '" + beanName + "'");
				}
				// Make sure bean class is actually resolved at this point.
				resolveBeanClass(mbd, beanName);

				// Prepare method overrides.
				try {
					mbd.prepareMethodOverrides();
				}
				catch (BeanDefinitionValidationException ex) {
					throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
							beanName, "Validation of method overrides failed", ex);
				}

				try {
					// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
					Object bean = resolveBeforeInstantiation(beanName, mbd);
					if (bean != null) {
						return bean;
					}
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"BeanPostProcessor before instantiation of bean failed", ex);
				}

				Object beanInstance = doCreateBean(beanName, mbd, args);
				if (logger.isDebugEnabled()) {
					logger.debug("Finished creating instance of bean '" + beanName + "'");
				}
				return beanInstance;
			}
		}, acc);
	}

 

 

     参考代码,可将这个过程分为 4 步:

1)       解决 Bean Class 类型

主要用于保证 RootBeanDefinition 具有 Class 信息

2)       处理重写的方法

用来验证重写的方法是否合法,防止将来反射调用报错

3)       resolveBeforeInstantiation

Bean 实例 之前, 容器级别生命周期接口方法调用 InstantiationAwareBeanPostProcessor. postProcessBeforeInstantiation(beanClass, beanName)

4)       调用 doCreateBean(beanName,rbd,args) 方法

 

这个方法就复杂一点了,首先它会包装 BeanWrapper 对象,将 bean 对象包装到一个 BeanWrapper 对象中,然后对 MergedBeanDefinitionPostProcessor 接口的 Bean 进行回调,接着会标识 Singleton Factory( 如果需要的话 ) ,接下来是 populateBean initializeBean 。最后根据 Bean Scope 决定让 Spring 来继续管理其生命周期还是交给客户端来管理, Spring 会为其注册 DisposableBean ,具体参见 registerDisposableBeanIfNecessary(beanName, bean, mbd)

populateBean 可以简单认为是设置 Bean properties ,具体:     

Ø  BeanDefinition 中获取 Properties’ Values

Ø  调用 InstantiationAwareBeanPostProcessor . postProcessAfterInstantiation 方法

Ø  Bean 自动装配处理

Ø  调用 InstantiationAwareBeanPostProcessor . postProcessProperty Values 方法

Ø  依赖检查 ( 如果需要的话 )

Ø  使 Properties Values 生效

 

initializeBean 方法在 Bean properties 生效后执行,具体:

Ø  实现 BeanNameAware bean 设置 beanName

Ø  实现 BeanClassLoaderAware bean 设置 beanClassLoader

Ø  实现 BeanFactoryAware bean 设置 beanFactory

Ø  调用 BeanPostProcessor . postProcess BeforeInitialization 方法,我们在这一步可以对 Bean 对象进行修改

Ø  Invoke init method ,调用 afterPropertiesSet() 或指定的初始化方法

Ø  调用 BeanPostProcessor . postProcess AfterInitialization 方法

      到此,核心的 Bean 生产装配功能都在 AbstractAutowireCapableBeanFactory 实现了,下层的 DefaultListableBeanFactory 继承这些功能的同时再实现可配置的功能 from ConfigurableListableBeanFactory 。另外,它还实现了 BeanDefinitionRegistry 。做为 full fledged BeanFactory DefaultListableBeanFactory 已经可以为客户端使用了,但是需要自己编程使用:

//测试Bean
public class Person {

	String name;
	Address address;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Address getAddress() {
		return address;
	}
	public void setAddress(Address address) {
		this.address = address;
	}
	@Override
	public String toString() {
		return name + "@" + address.getName();
	}
}

public class Address {

	String name;
	public Address(String name){
		this.name = name;
	}
}
//客户端
public class DefaultListableBeanFactoryTest {

	public static void main(String[] args){
		DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
		wireBeans(beanFactory);
		//使用
		Person p = (Person) beanFactory.getBean("newHier");
		System.out.println(p.toString());
	}

	private static BeanFactory wireBeans(BeanDefinitionRegistry registry) {
		RootBeanDefinition personBean = new RootBeanDefinition(Person.class);
		RootBeanDefinition addressBean = new RootBeanDefinition(Address.class);
		
		//将Bean注册到容器
		registry.registerBeanDefinition("newHier", personBean);
		registry.registerBeanDefinition("newHierAddress", addressBean);
		//通过构造方法为addressBean注入属性
		ConstructorArgumentValues argValues = new ConstructorArgumentValues();
		argValues.addIndexedArgumentValue(0, "Shilong Road");
		addressBean.setConstructorArgumentValues(argValues);
		//通过setter为personBean注入属性
		MutablePropertyValues propertiesValues = new MutablePropertyValues();
		propertiesValues.addPropertyValue(new PropertyValue("name","Wilson"));
		propertiesValues.addPropertyValue(new PropertyValue("address",addressBean));
		personBean.setPropertyValues(propertiesValues);
		
		//完成bean注册,返回BeanFactory
		return (BeanFactory)registry;
	}
}

   执行客户端测试,输入[email protected] Road

 

    作为本文的结尾,简单说两句类图中最底层的XmlBeanFactory,其实就是方便我们用Xml文件来配置,这样就不用那么麻烦的使用DefaultListableBeanFactory编程了。我们可以看到XmlBeanFactory依赖于XmlBeanDefinitionReader,这个Reader就是用来读取并解析Xml配置文件的。