A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

二十二道灰

初级黑马

  • 黑马币:

  • 帖子:

  • 精华:

© 二十二道灰 初级黑马   /  2017-9-21 14:52  /  1160 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 二十二道灰 于 2017-9-21 14:58 编辑

SPRING的BEAN的创建

用面向对象的方式理解spring
​        我们大家从第一天学spring的时候,都被灌输了这么一个理念,spring是一个面向切面的编程框架。但是我学到现在了,我觉得这个spring其实并不是面向切面的这么一个开发手段,我更偏向于叫他是一个面向对象,或者说是面向bean的开发框架。我给大家稍微解释一下我为什么这样想。
file://F:\自己写的笔记\技术演讲\img\5.png?lastModify=1505976452
​        这是我们第一天学spring的时候我们从spring官网上看到的这么一个图。当时我们什么都不知道,并不知道下边的三个组件在spring中的具体是什么位置,然后我们第一天学了Spring中的bean注入,是对bean的操作。
​        第二天学习的是ioc和aop,ioc就不用说了,是bean之间的关系,aop呢,是增强。那么增强,我觉得可以用这么一种逻辑来解释。我们都知道aop是动态代理的这么一种方式体现的。分别是jdk的动态代理和cglib的动态代理两种表现形式。这个增强的过程呢,是在整个java代码在运行的时候当他走到我们要增强的地方的时候,不走以前的逻辑,走我们自己增强的逻辑。那么我们是不是可以说这个框架其实还是在操纵bean?
       第三天学习的是spring的JDBC模板和事务。我认为哈,jdbc已经不是spring的主要任务了,事务的增强又是aop的一种体现。那么我说了这么多,总结一下,我认为spring这个框架从框架自己的角度看,并不代表大多数哈,这个框架实际上是一个面向对象的框架。
Spring中三大部件的关系:
​        我们用spring的关键入口时什么?就是bean。使用Spring可以让我们不再new对象,将这个工作交给beanfactory,然后我们在对对象进行操作的时候,spring帮我们映射这个,映射那个(这个操作我认为就是生成代理对象AOP的重要部分),而这个乱七八糟的做什么,就是spring核心包做的事情,而这里也就解释了很多人之前的一个问题,为什么在声明对象的时候一定要用接口去接收。
​        那么我们做一个比喻,如果我们把一个java程序比作是一场演出的话,那么bean就是这场演出的演员context是承载演出的舞台背景,core就是演出的必要道具。这三个元素是不可分割的。
bean的创建过程
​        我们都知道Spring是用了工厂模式给我们创建对象,底层是实现getobject接口,那么这三个是如何联系在一起的?接下来我带大家稍微看一点源码来看一下bean的生产过程:
​        首先我们要带着目的,要看什么的源码,我之前说了,bean是这些程序的入口,并且bean的包下大多都实现了beanfactory这样一个东西,我们先进来看一下,看到的是这是一个总接口,有很多方法,但是当我们打开他的实现类的时候,发现太多了,那么接下来我给大家介绍他下边的三个大接口:
​        HierarchicalBeanFactory:分等级的bean工厂
​        AutowireCapableBeanFactory:这个接口是装配那些不在xml中的bean。具体的方法我没有去看,但是这个跟我们目前所学的差的有点大,所以我没有深究,如果有兴趣的同学可以看一下。
​        ListableBeanFactory:表示可列表化的。我们就找这个
​        在这个下边我们找的第一个抽象类,是abstractApplicationContext。点进去之后,搜索init(初始化)这样一个词语,然后,我们看到了结束工厂初始化这样一行。我们都知道,java在运行的时候是按照我们从上往下的这么一个线性的顺序执行的,那么我们是不是可以说在这一行之前,他一定做了些什么,然后对工厂进行了设置:
  
   public void refresh() throws BeansException, IllegalStateException {
        Object arg0 = this.startupShutdownMonitor;
        synchronized(this.startupShutdownMonitor) {
           this.prepareRefresh();
           ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
          //创建beanfactory
           this.prepareBeanFactory(beanFactory);
           try {
            //注册实现了BeanFactoryPostProcessors的接口类
              this.postProcessBeanFactory(beanFactory);
             //初始化和执行BeanFactoryPostProcessors
                  this.invokeBeanFactoryPostProcessors(beanFactory);
             //初始化和执行BeanPostProcessors
              this.registerBeanPostProcessors(beanFactory);
             //初始化MessageSource
              this.initMessageSource();
             //初始化ApplicationEventMulticaster
              this.initApplicationEventMulticaster();
             //重新刷新他的子类实现的方法
              this.onRefresh();
             //监听事件
              this.registerListeners();
             //beanFactory的初始化
            this.finishBeanFactoryInitialization(beanFactory);
             //事件
              this.finishRefresh();
           } catch (BeansException arg8) {
             ......
           } finally {
              this.resetCommonCaches();
           }
  ​
        }
     }
那么当我们看到这里,就大概知道我们要看什么了,点进去那个beanfactory之后,是如下代码:
  
  protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        if(beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
           beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));
        }
  ​
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        String[] arg2 = weaverAwareNames;
        int arg3 = weaverAwareNames.length;
  ​
        for(int arg4 = 0; arg4 < arg3; ++arg4) {
           String weaverAwareName = arg2[arg4];
           this.getBean(weaverAwareName);
        }
  ​
        beanFactory.setTempClassLoader((ClassLoader)null);
        beanFactory.freezeConfiguration();
    //实例化bean
        beanFactory.preInstantiateSingletons();
     }
preInstantiateSingletons 预处理一个单例
​        当我们点进去的时候,很不好意思,进了接口,那么第一件事就去找他的下一层,很荣幸,我们又找到了他的方法。因为太长,我就不贴出来了,大家自己去看。
然后我们再来看代码:
  
    public void preInstantiateSingletons() throws BeansException {
        if(this.logger.isDebugEnabled()) {
           this.logger.debug("Pre-instantiating singletons in " + this);
        }
  ​
        ArrayList beanNames = new ArrayList(this.beanDefinitionNames);
        Iterator arg1 = beanNames.iterator();
  ​
        while(true) {
           while(true) {
              String beanName;
              RootBeanDefinition singletonInstance;
              do {
                 do {
                    do {
                       if(!arg1.hasNext()) {
                          arg1 = beanNames.iterator();
  ​
                          while(arg1.hasNext()) {
                             beanName = (String)arg1.next();
                             Object singletonInstance1 = this.getSingleton(beanName);
                             if(singletonInstance1 instanceof SmartInitializingSingleton) {
                                SmartInitializingSingleton smartSingleton1 = (SmartInitializingSingleton)singletonInstance1;
                                if(System.getSecurityManager() != null) {
                                   AccessController.doPrivileged(new 3(this, smartSingleton1), this.getAccessControlContext());
                                } else {
                                   smartSingleton1.afterSingletonsInstantiated();
                                }
                             }
                          }
  ​
                          return;
                       }
  ​
                       beanName = (String)arg1.next();
                       singletonInstance = this.getMergedLocalBeanDefinition(beanName);
                    } while(singletonInstance.isAbstract());
                 } while(!singletonInstance.isSingleton());
              } while(singletonInstance.isLazyInit());
  ​
              if(this.isFactoryBean(beanName)) {
                 FactoryBean smartSingleton = (FactoryBean)this.getBean("&" + beanName);
                 boolean isEagerInit;
                 if(System.getSecurityManager() != null && smartSingleton instanceof SmartFactoryBean) {
                    isEagerInit = ((Boolean)AccessController.doPrivileged(new 2(this, smartSingleton), this.getAccessControlContext())).booleanValue();
                 } else {
                    isEagerInit = smartSingleton instanceof SmartFactoryBean && ((SmartFactoryBean)smartSingleton).isEagerInit();
                 }
  ​
                 if(isEagerInit) {
                    this.getBean(beanName);
                 }
              } else {
                 this.getBean(beanName);
              }
           }
        }
     }
这里有一个特殊的bean,就是FactoryBean,点进去之后,发现他是一个接口:
那么我们知道了,如果是我们平常的时候,如果要产生一个实例对象,只要继承这个接口,然后调用他的getobject方法就行了。​
原理我们都听老师讲过,但是自己从源码中找到整个的源码,流程还是很开心的。给大家分享一下,希望大家也能从中学到一些知识。

5.png (130.21 KB, 下载次数: 3)

5.png

评分

参与人数 1黑马币 +2 收起 理由
播妞 + 2 很给力!

查看全部评分

3 个回复

倒序浏览
很透彻,很清晰,不错
回复 使用道具 举报
大神大神
回复 使用道具 举报
播妞来赞一个
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马