创世纪1.0

创世纪1.0

知其然,知其所以然。从历史开始解读spring前世今生。

大致浏览一下以下几个jar包,筛选出几个特别的类作为切入点(建议下载对应版本代码查阅)

  1. context 上下文环境
    • ApplicationContext/AbstractApplicationContext/ClassPathXmlApplicationContext
    • MessageSource/AbstractMessageSource/StaticMessageSource
    • ApplicationListener/ContextClosedEvent
    • package:
      • context
      • ejb
      • jndi
      • mail
      • remoting
      • scheduing
      • ui
      • validation
  2. core 核心,提供公共支持
    • NestedRuntimeException/BeansException
    • BeanWrapper/BeanWrapperImpl
    • package:
      • beans
      • core
      • util
  3. beans IOC/DI基础
    • BeanWrapper/BeanWrapperImpl
    • BeanFactory/AbstractBeanFactory/DefaultListableBeanFactory
    • FactoryBean/PropertiesFactoryBean
    • package:
      • beans
      • core
      • util
  4. aop 切面支持
    • AopProxy/Cglib2AopProxy
    • AopProxyFactory/DefaultAopProxyFactory
    • AopContext
    • AdvisorAdapter/BeforeAdviceAdapter
    • MethodMatcher
    • Advisor
    • package:
      • aop
      • metadata
  5. web spring框架对接web容器支持
    • WebApplicationContext/XmlWebApplicationContext
    • ContextLoaderListener/ContextLoaderServlet
    • package:
      • bind
      • context
      • filter
      • multipart
      • util
  6. dao
  7. orm

从选取出来的一些接口、类可以得知以下几点

  1. 广泛的使用设计模式
    • 工程
    • 代理
    • 适配器
    • 观察者
  2. 命名规范严谨
    • 命名关联关系

上述设计模式可以移步spring中的设计模式阅读

以上几个包的关系可以理解为,context基于beans构建了spring的框架环境,core提供了公共支持,aop提供了切面编程的基础。dao、orm在后面的版本移除,不累述。

IOC/DI

通过xml配置bean,对象托管到spring,生命周期由spring控制。默认使用单例生成bean对象。初始化步骤如下

  1. spring初始化载入bean配置文件(需要指定),并解析为元数据注册到beanDefinitionMap(String:RootBeanDefinition),beanDefinitionNames(String)
  2. 在beanFactory中会先初始化单例且非懒加载的bean到缓存singleCache中,需要注意的是初始化时也是调用getBean方法,首先从缓存取,取不到时再以单例的方式获取
  3. 在注入bean对象时调用beanFactory中的getBean方法获取
    1. 先从缓存单例中取,有即返回
    2. 取不到则获取元定义信息调用createBean方法创建,最终调用xxx.class.newInstance方法生成实例并调用populateBean方法注入其中引用的对象

核心代码围绕着BeanFactory开始,核心类如下:

  • AbstractBeanFactory,AbstractAutowireCapableBeanFactory,DefaultListableBeanFactory
  • RootBeanDefinition
  • BeanWrapperImpl

BeanFactory与FactoryBean

前面一直在说BeanFactory,那么FactoryBean又是什么又有什么作用了?

从上面BeanFactory的描述我们可以知道,我们Bean实例的获取均通过BeanFacotry,他统一管理了bean的实例化,实际上就是一个工厂

我们从FactoryBean接口定义来看,总共三个方法

  1. getObject
  2. getObjectType
  3. isSingleton

在看AbstractBeanFactory类中的getBean方法过程过程中我们发现在调用的getObjectForSharedInstance方法中有这么一段

// 简写后的逻辑,是工厂bean且不是工厂的引用
if (beanInstance instanceof FactoryBean) {
    if (!this.isFactoryDereference(name)) {
        FactoryBean factory = (FactoryBean)beanInstance;
        beanInstance = factory.getObject();
    }
}
<bean id="demo" class="com.jsmzr.demo.DemoFactory"></bean>

按照名字来获取bean实例时如果需要获取的是DemoFactory实例那么应该在名字前加"&"符号,即"&demo"

所以我们可以将FactoryBean与BeanFactory区分开了,BeanFactory是一个生产bean的工厂,而FactoryBean是一个工厂类型的bean,当从工厂中获取的bean是一个工厂bean且需要的不是工厂时会从中国FactoryBean中获取bean(bean的获取方式在FactoryBean中定义)。

如果还是有些混淆那么完全可以把FactoryBean理解为与一般的Bean一样,只是自身还带有工厂的特性。

框架环境

spring提供了一套运行时环境,我们可以将实例托管到spring。

从AbstractApplicationContext类中我们看到sprng初始化的步骤大概是

  1. 从配置文件获取bean配置
  2. 按照配置初始化bean

详见代码AbstractApplicationContext类refresh方法

web环境

我们知道spring只是一个框架,那么他是怎么接入web服务的了?用过老版本spring的人大概都记得,我们在spring+tomcat的时候会在tomcat的web.xml配置文件中配置用过监听器。web容器在初始化时会调用这个监听器中的初始化方法,即ContextLoaderListener的contextInitialized方法。

通过调用spring-web中的初始化方法,会在容器中初始化spring的环境,在这里spring提供了XmlWebApplicationContext作为web环境的支持。这里相当于是把spring环境嵌入了web容器,即我们web开发中的对象实例依然由spring来管理,容器依旧只是提供自己的容器功能,当容器关闭时也会销毁其中的spring环境

在这个版本中spring-web只是提供了一些较为基础的功能

  1. 托管到web容器
  2. 乱码解决过滤器
  3. 日志配置及支持
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值