Spring IOC之BeanFactory

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


执行客户端测试,输入Wilson@Shilong Road



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

猜你喜欢

转载自wang4674890.iteye.com/blog/1674961