文章目录
一、谈谈对Spring的理解
Spring是一个生态,可以构建java应用所需的一切基础设施。通常Spring指的就是 Spring Framework 。 spring 是一个轻量级的开源容器框架,是为了解决企业级应用开发的业务逻辑层和其他各层对象和对象直接的耦合问题。
二、Spring的优缺点
特点:
- 方便解耦,简化开发
通过 Spring 提供的 IOC 容器,我们可以将对象之间的依赖关系交由Spring 进行控制,避免硬编码所造成的过度程序耦合,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
即 Spring 集中管理对象,对象和对象之间的耦合度减低,方便维护对象。 - AOP 编程的支持
通过 Spring 提供的 AOP 功能,方便进行面向切面的编程,许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松应付。Spring 的 AOP 支持允许将一些通用任务如安全、事务、日志等进行集中式管理,从而提供了更好的复用。
即在不修改代码的情况下可以对业务代码进行增强,减少重复代码,提高开发效率,维护方便。 - 声明事物的支持
在 Spring 中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
即提高开发效率,只需要一个简单注解 @Transactional。 - 方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,在 Spring 里,测试不再是昂贵的操作,而是随手可做的事
情。例如:Spring 对 Junit4 支持,可以通过注解方便的测试 Spring 程序。
即 Spring 实现测试,使我们可以结合 junit 非常方便测试 Spring Bean SpringMVC - 方便集成各种优秀框架
Spring 不排斥各种优秀的开源框架,相反,Spring 可以降低各种框架的使用难度,Spring 提供了对各种优秀框架(如 Struts , Hibernate 、Hessian、Quartz)等的直接支持。
即拥有非常强大粘合度、集成能力非常,只需要简单配置就可以集成第三方框架。 - 降低 Java EE API 的使用难度
Spring 对很多难用的 Java EE API(如 JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些 Java EE API 的使用难度大为降低。
即简化开发, 帮我封装很多功能性代码 - Java 源码是经典学习范例
Spring 的源码设计精妙、结构清晰、匠心独用,处处体现着大师对Java 设计模式灵活运用以及对 Java 技术的高深造诣。Spring 框架源码无疑是 Java 技术的最佳实践范例。如果想在短时间内迅速提高自己的Java 技术水平和应用开发水平,学习和研究 Spring 源码将会使你收到意想不到的效果。
即学习到了 Spring 底层的实现、反射设计模式 都是我们值得学习,提供非常多的扩展接口供外部进行扩展。
缺点:
从应用层面来说是没有缺点的,简化开发,如果想深入到底层去了解就非常困难(上层使用越简单、底层封装得就越复杂)。源码缺点:由于spring 大而全(要集成这么多框架、提供非常非常多的扩展点,经过十多年的代码迭代) 代码量非常庞大 ,一百多万 对于去深入学习源码带来了一定困难。
三、Spring IOC
什么是Spring IOC
控制反转即 IOC (Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。
Spring IOC 负责创建对象,管理对象(通过依赖注入(DI),装配对象,配置对象,并且管理这些对象的整个生命周期。
对于 IOC 来说,最重要的就是容器。容器管理着 Bean 的生命周期,控制着 Bean 的依赖注入。
控制反转( IOC )的作用:
- 管理对象的创建和依赖关系的维护。对象的创建并不是一件简单的事,在对象关系比较复杂时,如果依赖关系需要程序员来维护的话,那是相当头疼的
- 解耦,由容器去维护具体的对象
- 托管了类的产生过程,比如我们需要在类的产生过程中做一些处理,最直接的例子就是代理,如果有容器程序可以把这部分处理交给容器,应用程序则无需去关心类是如何完成代理的
优点:用最小的代价和最小的侵入性使松散耦合得以实现,支持加载服务时的饿汉式初始化和懒加载
实现机制:Spring 中的 IOC 的实现原理就是工厂模式加反射机制
四、依赖注入(DI)
很多人把 IOC 和 DI 说成一个东西,笼统来说的话是没有问题的,但是本质上还是有所区别的,IOC 和 DI 是从不同的角度描述的同一件事,IOC 是从容器的角度描述,而 DI 是从应用程序的角度来描述,也可以这样说,IOC 是依赖倒置原则的设计思想,而 DI 是具体的实现方式。
在面向对象设计的软件系统中,底层的实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑。有一个对象出了问题,就可能会影响到整个流程的正常运转。现在,伴随着工业级应用的规模越来越庞大,对象之间的依赖关系也越来越复杂,经常会出现对象之间的多重依赖性关系,因此,架构师和设计师对于系统的分析和设计,将面临更大的挑战。对象之间耦合度过高的系统,必然会出现牵一发而动全身的情形。
由于引进了中间位置的“第三方”,也就是IOC容器,对象和对象之间没有了耦合关系, 它起到了一种类似“粘合剂”的作用,把系统中的所有对象粘合在一起发挥作用,如果没有这个“粘合剂”,对象与对象之间会彼此失去联系,这就是有人把IOC容器比喻成“粘合剂”的由来。
五、 IOC容器的加载过程
从概念态—>定义态的过程
- 实例化一个ApplicationContext的对象
- 调用bean工厂后置处理器完成扫描
- 循环解析扫描出来的类信息
- 实例化一个BeanDefinition对象来存储解析出来的信息
- 把实例化好的beanDefinition对象put到beanDefinitionMap当中缓存起来,以便后面实例化bean
- 再次调用其他bean工厂后置处理器
从定义态到纯净态
- 当然spring还会干很多事情,比如国际化,比如注册BeanPostProcessor等等,如果我们只关心如何实例化一个bean的话那么这一步就是spring调用 finishBeanFactoryInitialization方法来实例化单例的bean,实例化之前spring要做验证,需要遍历所有扫描出来的类,依次判断这个bean是否Lazy,是否prototype,是否 abstract等等
- 如果验证完成spring在实例化一个bean之前需要推断构造方法,因为spring实 例化对象是通过构造方法反射,故而需要知道用哪个构造方法
- 推断完构造方法之后spring调用构造方法反射实例化一个对象;注意这里说的是对象;这个时候对象已经实例化出来了,但是并不是一个完整的bean,最简单的体现是这个时候实例化出来的对象属性是没有注入,所以不是一个完整的bean
从纯净态到成熟态
- spring处理合并后的beanDefinition
- 判断是否需要完成属性注入
- 如果需要完成属性注入,则开始注入属性
初始化 - 判断bean的类型回调Aware接口
- 调用生命周期回调方法
- 如果需要代理则完成代理
创建完成
- put到单例池——bean完成——存在spring容器当中