Spring(2)-Spring IOC 之BeanFactory



Spring(2)-Spring IOC 之BeanFactory

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

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.postProcessPropertyValues方法

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

Ø 使Properties Values生效

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

Ø 实现BeanNameAware的bean设置beanName

Ø 实现BeanClassLoaderAware的bean设置beanClassLoader

Ø 实现BeanFactoryAware的bean设置beanFactory

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

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

Ø 调用BeanPostProcessor.postProcessAfterInitialization方法

到此,核心的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;
}
}

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