简单了解Spring

最近想学习一下spring框架,并把一些知识要点记录一下。

Spring框架关注于通过依赖注入、面向切面编程和消除样板式代码来简化企业级Java开发。

参考书:《Spring实战》 第三版

Spring的主要特性是依赖注入(DI)和面向切面编程(AOP)

为了降低Java开发的复杂性,Spring采取了以下4种关键策略:

  • 基于POJO的轻量级和最小侵入性编程
  • 通过依赖注入和面向切口编程实现松耦合
  • 基于切面和惯例进行声明式编程
  • 通过切面和模板减少样板式代码

依赖注入:
任何一个有实际意义的应用都是由两个或者更多的类组成,这些类相互之间进行协作来完成特定的业务逻辑。通常,每个对象负责管理与自己协作的对象(即它所依赖的对象)的引用,这将会导致高度耦合和难以测试的代码。
而通过依赖注入,对象的依赖关系将由负责协调系统中各个对象的第三方组件在创建对象时设定。对象无需自行创建或管理它们的依赖关系——依赖关系将被自动注入到需要它们的对象中去。

耦合:具有两面性。一方面,紧密耦合的代码难以测试,难以复用,难以理解。另一方面,一定程度的耦合又是必须的,完全没有耦合的代码什么也做不了。为了完成有实际意义的功能,不同的类必须以适当的方式进行交互。

Spring通过应用上下文(Application Context)装载Bean的定义,并把它们组装起来。Spring应用上下文全权负责对象的创建和组装。

依赖注入让相互协作的软件组件保持松散耦合,而AOP编程允许把遍布应用各处的功能分离出来形成可重用的组件。

面向切面编程往往被定义为促使应用程序分离关注点的一项技术。

系统由许多不同组件组成,每一个组件各负责一块特定功能。除了实现自身核心功能之外,这些组件还经常承担着额外的职责。诸如:日志、事务管理和安全此类的系统服务经常融入到有自身核心业务逻辑的组件中去,这些系统服务通常被称为横切关注点

AOP使这些服务模块化,并以声明的方式将它们应用到需要影响的组件中去。结果是这些组件具有更高的内聚性以及更加关注自身业务,完全不需要了解可能涉及的系统服务的复杂性。总之,AOP确保POJO保持简单。

容器是Spring框架的核心。Spring容器使用依赖注入管理构成应用的组件,它会创建相互协作的组件之间的关联。

Spring自带了几种容器实现,可以归为两种不同的类型:

Bean工厂(bean factories):是最简单的容器,提供基本的DI支持。由org.springframework.beans.factory.beanFactory接口定义。

应用上下文(application context):基于BeanFactory之上构建,并提供面向应用的服务。例如从属性文件解析文本信息的能力,以及发布应用事件给感兴趣的事件监听者的能力。由org.springframework.context.ApplicatonContext接口定义。

应用上下文更受欢迎。

Spring自带了几种类型的应用上下文,一下三种是最常用的:

ClassPathXmlApplicationContext——从类路径下的XML配置文件中加载上下文定义,把应用上下文定义文件当做类资源。

FileSystemXmlApplicationContext——读取文件系统下的XML配置文件并加载上下文定义。

XmlWebApplicationContext——读取Web应用下的XML配置文件并装载上下文定义。

加载代码都类似:

1
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");

使用FileSystemXmlApplicationContext和使用ClassPathXmlApplicationContext的区别在于:前者在指定的文件系统路径下查找xml文件;而后者是在所有的类路径(包含JAR文件)下查找xml文件。

Bean的生命周期:

1
2
3
4
5
6
7
8
9
10
1. Spring对bean进行实例化
2. Spring将值和bean的引用注入进Bean对应的属性中去
3. 如果Bean实现了BeanNameAware接口,Spring将Bean的ID传递给setBeanName()接口方法
4. 如果Bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()接口方法,将BeanFactory容器实例传入
5. 如果Bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()接口方法,将应用上下文的引用传入
6. 如果Bean实现了BeanPostProcessor接口,Spring将调用它们的postProcessorBeforeInitialization()接口方法
7. 如果Bean实现了Initialization接口,Spring将调用它们的afterPropertiesSet()接口方法。类似的,如果Bean使用了init-method声明了初始化方法,该方法也会被调用
8. 如果Bean实现了BeanPostProcessor接口,Spring将调用它们的postProcessorAfterInitalization()方法
9. 此时此刻,Bean已经准备就绪,可以被应用程序使用了,它们将一直驻留在应用上下文中,直到该应用上下文被销毁
10. 如果Bean实现了DisposableBean接口,Spring将调用它的destory()接口方法。同样,如果Bean使用destory-method声明了销毁方法,该方法也会被调用