1 引言
Spring是一个轻量级Java开发框架,最早由Rod Johnson创建,目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题,它是一个分层的JavaSE/JavaEE full-stack(全栈式)轻量级开源框架,为开发Java应用程序提供全面的基础架构支持。Spring负责基础架构,因此Java开发者可以专注于应用程序开发。Spring最根本的使命是解决企业级应用开发的复杂性,即简化Java开发。
Spring可以做很多事情,它为企业级开发提供了丰富的功能,但是这些功能的底层都依赖于它的两个核心特性,也就是依赖注入(dependency injection,DI)和面向切面编程(aspect-oriented programming, AOP)。
为了降低Java开发的复杂性,Spring采取了以下4种关键策略:
- 基于POJO的轻量级和最小侵入性编程;
- 通过依赖注入和面向接口实现松耦合;
- 基于切面和惯例进行声明式编程;
- 通过切面和模板减少样板式代码。
2 Spring组成模块
Spring总共大约有20个模块,由1300多个不同的文件构成。这些组件被分别整合在核心容器(Core Container)、AOP(Aspect Oriented Programming)和设备支持(Instrmentation)、数据访问与集成(Data Access/Integeration)、Web、消息(Messaging)、Test等6个模块中。以下是Spring模块结构图:
- Spring Core:提供了框架的基本组成部分,包括控制反转(Inversion of Control,IoC)和依赖注入(Dependency Injection,DI)功能。
- Spring Beans:提供了BeanFactory,是工厂模式的一个经典实现,Spring将管理对象成为Bean。
- Spring Context:构建于Core封装包基础上的Context封装包,提供一种框架式的对象访问方法。
- Spring JDBC:提供了一个JDBC的抽象层,消除了繁琐的JDBC编码和数据库厂商特有的错误代码解析,用于简化JDBC。
- Spring AOP:提供了面向切面的编程实现,让你可以自定义拦截器、切点等。
- Spring Web:提供了针对Web开发的集成特性,例如文件上传,利用Servlet Listeners 进行IoC容器初始化和针对Web的ApplicationContext。
- Spring Test:主要为测试提供支持的,支持使用JUnit或TestNG对Spring组件进行单元测试和集成测试。
3 Spring IOC原理
Spring通过一个配置文件描述Bean及Bean之间的依赖关系,利用Java语言的反射功能实例化Bean并建立Bean之间的依赖关系。Spring的IoC容器在完成这些底层工作的基础上,还提供了Bean实例缓存、生命周期管理、Bean实例代理、事件发布、资源装载等高级服务。
Spring启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相应的Bean配置注册表,然后根据这张注册表实例化Bean,装配好Bean之间的依赖关系,为上层应用提供准备就绪的运行环境。其中Bean缓存池是通过HashMap实现的。
3.1 Spring为Bean定义了5种作用域
singleton(单例)、prototype(原型)、request、session和global session。
- singleton:单例模式,Spring IoC容器种只会存在一个共享的Bean实例,无论有多少个Bean引用它,始终指向同一对象。该模式在多线程下是不安全的。Singleton作用域是Spring中的缺省作用域,也可以显式的将Bean定义为singleton模式。
- prototype:原型模式,每次通过Spring容器获取prototype定义的bean时,容器都将创建一个新的Bean实例,每个Bean实例都有自己的属性和状态,而singleton全局只有一个对象。一般,对有状态的bean使用prototype作用域,而对无状态的bean使用singleton作用域。
- request:在一次http请求中,容器会返回该Bean的同一实例。而对不同的http请求则会产生新的bean,而且该bean仅在当前http request内有效,当http请求结束,该bean实例也将会被销毁。
- session:在一次session中,容器会返回该Bean的同一实例。而对不同的session请求则会创建新的实例,该bean实例仅在当前session内有效。同http请求相同,每一次session请求创建新的实例,而不同的实例之间不共享属性,且实例仅在自己的session请求内有效,请求结束,则实例将被销毁。
- global session:在一个全局的http session中,容器会返回该bean的同一实例,仅在使用portlet context时有效。
3.2 Spring Bean的生命周期
- 实例化:实例化一个Bean,也就是我们通常说的new。
- IoC依赖注入:按照Spring上下文对实例化的Bean进行配置,也就是IoC注入。
- setBeanName实现:如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String)方法,此处传递的就是Spring配置文件中Bean的ID值。
- BeanFactoryAware实现:如果Bean已实现BeanFactoryAware接口,会调用它实现的setBeanFactory(String)方法,该方法传递的是Spring工厂自身(可以用这个方式来获取其它Bean,只需在Spring配置文件中配置一个普通的Bean就可以)。
- ApplicationContextAware 实现:如果 Bean 已经实现了 ApplicationContextAware 接口,会调用setApplicationContext(ApplicationContext)方法,传入 Spring 上下文(同样这个方式也可以实现
步骤 4 的内容,但比 4 更好,因为 ApplicationContext 是 BeanFactory 的子接口,有更多的实现
方法) - postProcessBeforeInitialization接口实现,初始化预处理:如果这个 Bean 关联了BeanPostProcessor 接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor 经常被用作是 Bean 内容的更改,并且由于这个是在 Bean 初始化结束时调用那个的方法,也可以被应用于内存或缓存技术。
- init-method:如果 Bean 在 Spring 配置文件中配置了 init-method 属性会自动调用其配置的初始化方法。
- postProcessAfterInitialization:如果这个 Bean 关联了 BeanPostProcessor 接口,将会调用postProcessAfterInitialization(Object obj, String s)方法。
至此,以上工作完成以后就可以应用这个 Bean 了,那这个 Bean 是一个 Singleton 的,所以一般情况下我们调用同一个 id 的 Bean 会是在内容地址相同的实例,当然在 Spring 配置文件中也可以配置非Singleton。
- Destroy 过期自动清理阶段:当 Bean 不再需要时,会经过清理阶段,如果 Bean 实现了 DisposableBean 这个接口,会调用那个其实现的 destroy()方法; destroy-method 自配置清理
- 最后,如果这个 Bean 的 Spring 配置中配置了 destroy-method 属性,会自动调用其配置的销毁
方法。 - bean 标签有两个重要的属性(init-method 和 destroy-method)。用它们你可以自己定制初始化
和注销方法。它们也有相应的注解(@PostConstruct 和@PreDestroy)。
4 Spring AOP原理
“横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,
并将其命名为"Aspect”,即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用
的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。使用"横切"技术,AOP 把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
AOP有几个核心概念:
- 切面(aspect):类是对物体特征的抽象,切面就是对横切关注点的抽象
- 横切关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点。
- 连接点(joinpoint):被拦截到的点,因为 Spring 只支持方法类型的连接点,所以在 Spring 中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器。
- 切入点(pointcut):对连接点进行拦截的定义
- 通知(advice):所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异 常、最终、环绕通知五类。
- 目标对象:代理的目标对象
- 织入(weave):将切面应用到目标对象并导致代理对象创建的过程
- 引入(introduction):在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段。
4.1 AOP 主要应用场景
- Authentication 权限
- Caching 缓存
- Context passing 内容传递
- Error handling 错误处理
- Lazy loading 懒加载
- Debugging 调试
- logging, tracing, profiling and monitoring 记录跟踪 优化 校准
- Performance optimization 性能优化
- Persistence 持久化
- Resource pooling 资源池
- Synchronization 同步
- Transactions 事务
5 Spring MVC原理
Spring 的模型-视图-控制器(MVC)框架是围绕一个 DispatcherServlet 来设计的,这个 Servlet 会把请求分发给各个处理器,并支持可配置的处理器映射、视图渲染、本地化、时区与主题渲染等,甚至还能支持文件上传。
返回面试宝典