一步一步学习Spring(2)-Spring IOC 之BeanFactory

我的淘宝:http://my-chocolate.taobao.com

 

做过不少项目,用到最多的框架当属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(如果需要的话),接下来是populateBeaninitializeBean。最后根据BeanScope决定让Spring来继续管理其生命周期还是交给客户端来管理,Spring会为其注册DisposableBean,具体参见registerDisposableBeanIfNecessary(beanName, bean, mbd)

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

Ø  BeanDefinition中获取Properties’ Values

Ø  调用InstantiationAwareBeanPostProcessor. postProcessAfterInstantiation方法

Ø  Bean自动装配处理

Ø  调用InstantiationAwareBeanPostProcessor.postProcessPropertyValues方法

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

Ø  使Properties Values生效

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

Ø 实现BeanNameAwarebean设置beanName

Ø 实现BeanClassLoaderAwarebean设置beanClassLoader

Ø 实现BeanFactoryAwarebean设置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配置文件的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值