Spring框架学习[IoC容器高级特性](二)

2014-11-24 03:11:10 · 作者: · 浏览: 1
ultListableBeanFactory对配置lazy-init属性单态Bean的预实例化:
  • //对配置lazy-init属性单态Bean的预实例化 public void preInstantiateSingletons() throws BeansException {
  • if (this.logger.isInfoEnabled()) { this.logger.info(Pre-instantiating singletons in + this);
  • } //在对配置lazy-init属性单态Bean的预实例化过程中,必须多线程同步,以确
  • //保数据一致性 synchronized (this.beanDefinitionMap) {
  • for (String beanName : this.beanDefinitionNames) { //获取指定名称的Bean定义
  • RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); //Bean不是抽象的,是单态模式的,且lazy-init属性配置为false
  • if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { //如果指定名称的bean是创建容器的Bean
  • if (isFactoryBean(beanName)) { //FACTORY_BEAN_PREFIX=”&”,当Bean名称前面加”&”符号
  • //时,获取的是产生容器对象本身,而不是容器产生的Bean. //调用getBean方法,触发容器对Bean实例化和依赖注入过程
  • final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName); //标识是否需要预实例化
  • boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
  • //一个匿名内部类 isEagerInit = AccessController.doPrivileged(new PrivilegedAction () {
  • public Boolean run() { return ((SmartFactoryBean) factory).isEagerInit();
  • } }, getAccessControlContext());
  • } else {
  • isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit(); }
  • if (isEagerInit) { //调用getBean方法,触发容器对Bean实例化和依赖注入过程
  • getBean(beanName); }
  • } else {
  • //调用getBean方法,触发容器对Bean实例化和依赖注入过程 getBean(beanName);
  • } }
  • } }
  • }

    通过对lazy-init处理源码的分析,我们可以看出,如果设置了lazy-init属性,则容器在完成Bean定义的注册之后,会通过getBean方法,触发对指定Bean的初始化和依赖注入过程,这样当应用第一次向容器索取所需的Bean时,容器不再需要对Bean进行初始化和依赖注入,直接从已经完成实例化和依赖注入的Bean中取一个线程的Bean,这样就提高了第一次获取Bean的性能。

    3.FactoryBean的实现:

    在Spring中,有两个很容易混淆的类:BeanFactory和FactoryBean。
    BeanFactory:Bean工厂,是一个工厂(Factory),我们Spring IoC容器的最顶层接口就是这个BeanFactory,它的作用是管理Bean,即实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。

    FactoryBean:工厂Bean,是一个Bean,作用是产生其他bean实例。通常情况下,这种bean没有什么特别的要求,仅需要提供一个工厂方法,该方法用来返回其他bean实例。通常情况下,bean无须自己实现工厂模式,Spring容器担任工厂角色;但少数情况下,容器中的bean本身就是工厂,其作用是产生其它bean实例。

    当用户使用容器本身时,可以使用转义字符”&”来得到FactoryBean本身,以区别通过FactoryBean产生的实例对象和FactoryBean对象本身。在BeanFactory中通过如下代码定义了该转义字符:

    StringFACTORY_BEAN_PREFIX = &;

    如果myJndiObject是一个FactoryBean,则使用&myJndiObject得到的是myJndiObject对象,而不是myJndiObject产生出来的对象。

    (1).FactoryBean的源码如下:

    [java]
    1. //工厂Bean,用于产生其他对象 public interface FactoryBean {
    2. //获取容器管理的对象实例 T getObject() throws Exception;
    3. //获取Bean工厂创建的对象的类型 Class getObjectType();
    4. //Bean工厂创建的对象是否是单态模式,如果是单态模式,则整个容器中只有一个实例 //对象,每次请求都返回同一个实例对象
    5. boolean isSingleton(); }

      (2). AbstractBeanFactory的getBean方法调用FactoryBean:

      在第5篇博客我们分析Spring Ioc容器实例化Bean并进行依赖注入过程的源码时,提到在getBean方法触发容器实例化Bean的时候会调用AbstractBeanFactory的doGetBean方法来进行实例化的过程,源码如下:

      [java]
      1. //真正实现向IoC容器获取Bean的功能,也是触发依赖注入功能的地方 @SuppressWarnings(unchecked)
      2. protected T doGetBean( final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
      3. throws BeansException { //根据指定的名称获取被管理Bean的名称,剥离指定名称中对容器的相关依赖
      4. //如果指定的是别名,将别名转换为规范的Bean名称 final String beanName = transformedBeanName(name);
      5. Object bean; //先从缓存中取是否已经有被创建过的单态类型的Bean,对于单态模式的Bean整
      6. //个IoC容器中只创建一次,不需要重复创建 Object sharedInstance = getSingleton(beanName);
      7. //IoC容器创建单态模式Bean实例对象 if (sharedInstance != null && args == null) {
      8. if (logger.isDebugEnabled()) { //如果指定名称的Bean在容器中已有单态模式的Bean被创建,直接返回
      9. //已经创建的Bean if (i