九零后大叔
技术人的点点滴滴

beanfactory篇-(十)spring框架的感性认识

回顾:通过前面一系列的文章的了解,对于spring的常用和非常用用法都有了一定的了解。本章节我们不探讨任何一些spring的功能的使用,也暂时不阅读任何的源码。我们先总体的回顾和总结一下前面的知识,对于spring有一个感性的认识和了解。


1. spring的重要概念的总结

[1]BeanFactory是基础版或者标配版的spring,提供spring最核心最基础的功能;ApplicationContext是高配版或者豪华办的spring,提供了除核心和基础功能外的常用的扩展功能。

[2]既然ApplicationContext是对BeanFactory的扩展,那么是不是ApplicationContext的底层间接的继承至BeanFactory或者间接的持有BeanFactory呢?我们看看下面的的过程就明白了。

首先从下图,我们可以看到XmlBeanFactory继承至DefaultListableBeanFactory类

其次从下两张图,我们可以看到ClassPathXmlApplicationContext继承至AbstractXmlApplicationContext,而AbstractXmlApplicationContext继承至AbstractRefreshableConfigApplicationContext,而AbstractRefreshableConfigApplicationContext继承至AbstractRefreshableApplicationContext,而AbstractRefreshableApplicationContext类持有一个DefaultListableBeanFactory对象。


从上述两组图,我们基本上可以确定DefaultListableBeanFactory类是我们的spring的最小核心实现,不管是XmlBeanFactory继承至DefaultListableBeanFactory,还是ClassPathXmlApplicationContext持有DefaultListableBeanFactory,都是对DefaultListableBeanFactory扩展而已。只不过XmlBeanFactory基本上没有做很多功能的扩展,只是简单的继承了一下DefaultListableBeanFactory类,而ClassPathXmlApplicationContext通过持有DefaultListableBeanFactory的方式,来对DefaultListableBeanFactory进行了大量的功能扩展。

[3]一个XmlBeanFactory对象或者ClassPathXmlApplicationContext对象,就是一个spring容器。而创建一个XmlBeanFactory对象或者ClassPathXmlApplicationContext对象的过程,就可以理解为启动spring容器或者启动spring框架的过程。

    //使用低配版的spring开发业务(不太常用)
    XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
    UserService userService = beanFactory.getBean(UserService.class);
    User user = userService.findUserById(100L);
    System.out.println(JSONObject.toJSONString(user));

    //使用高配版的spring框架来开发业务(除了web类服务外,像定时服务,消息消费服务一般都是这种方式启动一个spring服务的)
    ClassPathXmlApplicationContext cac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    UserService userService = cac.getBean(UserService.class);
    User user = userService.findUserById(100L);
    System.out.println(JSONObject.toJSONString(user));

[4]XmlBeanFactory这个低配版的spring的整体工作过程分两个核心步骤:一、创建一个XmlBeanFactory对象(创建这个对象的实质是将所有的bean的描述信息注册到一个Map中去);二、通过getBean方法,创建bean对象(实质上是根据一的Map种bean描述信息创建对应的bean对象)


2. spring的的核心过程的一些问题

前面我们刚刚提到了spring的整体工作过程分两个部分,一个是注册bean描述信息,一个是根据这些bean描述信息创建对象。要理解前面这两个部分,我们首先要将下面的三个问题要先捋清楚。

问题一:什么是bean描述信息?
bean描述信息又成为bean元数据,其实更应该称为bean描述信息,因为这样称呼更加贴切。bean描述信息和我们人的档案非常的类似,我们的档案详细描述了我们一个人从出生到目前为止,所有的就学和工作经历等等。同样的,每一个bean都有一份描述信息(或者说“档案”),决定了这个bean应该被创建成为什么样(如bean的名称,父bean的名称,bean的scope范围,bean是否是延迟加载,bean是否由其它的factorybean生成的等等信息,bean有哪些其它属性)。有了这些信息之后
,我们的spring容器就能根据这些描述信息创建对应的bean了。

bean描述信息在不同的阶段,是被不通的载体所承载的。在源码阶段,一段applicationContext.xml的bean配置信息就是我们的某个bean描述信息,如下所示:

<bean id="userService" name="userService" class="com.minesoft.tutorial.service.UserServiceImpl"
      scope="singleton"
      autowire="byType"
      abstract="false"
      lazy-init="true"
      factory-bean="userServiceXmlFactoryBean"
      factory-method="createUserService"
/>

而当我们的spring容器启动成功后(也就是一个XmlBeanFactory对象被创建成功后),上面的这段xml描述信息也就被封装成了一个RootBeanDefinition(继承至AbstractBeanDefinition)对象。如下图所示:

而从一段bean标签信息被一步一步的解析并最终封装成为一个RootBeanDefinition(继承至AbstractBeanDefinition)对象的过程,也就是spring容器的启动过程。

问题二:Map在哪儿,被什么对象所持有?
我们刚刚提到了一段bean标签信息被一步一步的解析并最终封装成为一个BeanDefinition对象的过程,那么这个对象总得存放到一个Map也好,List也好,Set也好,总之得存放到一个容器中去。不然后续使用getBean方法创造一个bean的时候,从何处拿到bean描述信息呢?从下图我们知道最终存放到了DefaultListableBeanFactory对象所持有的beanDefinitionMap对象中。

问题三:创建bean对象是通过new的方式创建的,还是通过反射的方式创建的,还是其它方式创建的?
bean对象的创建方式有多种多样,有的是spring通过反射创建的,有的是spring调用用户的一些扩展代码实现的,具体实现方式得看每一个bean描述信息的具体配置。通过前面的文章的学习,我们知道了至少三种方式能创建bean对象(xml配置或者注解最底层都是通过反射的方式创建,开发者实现FactoryBean接口自定义创建,开发者实现InstantiationAwareBeanPostProcessor接口并在postProcessBeforeInstantiation方法中创建)。


更多知识请关注公众号

赞(0) 赏一下
未经允许不得转载:九零后大叔的技术博客 » beanfactory篇-(十)spring框架的感性认识
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

九零后大叔的技术博客

联系我们联系我们

感谢您的支持

支付宝扫一扫打赏

微信扫一扫打赏