前言
我在知乎上看到这样一个话题,关于程序员的:
听同学说干码农这行每天都要加班,这样的话,不就没精力做别的事情了。有个师兄做 IT 销售,不太辛苦,生活还算是美滋滋,是真的吗?我也知道社会上干哪一行都不容易,可是好像码农生活确实单调无聊。天天敲代码,日常嗨一嗨都没时间,更别说有精力谈恋爱了。想问问正在工作的各位前辈,你们的生活是怎么样的?
开门见山、开诚布公地说吧,我是一个对技术没有很大热情的程序员。这样说会不会遭到一些同学们的 DISS?不管了,反正我知道一不小心又甩了两个成语,感觉自己挺有才华的。你们要是枯燥地笑了,请在文末给我一个大大的赞。
1. Spring 特点
Spring 主要有如下特点:
- 轻量级:Spring 是非侵入式,其中的对象不依赖 Spring 的特定类;
- 控制反转(IoC):通过 IoC,促进了低耦合,一个对象依赖的其他对象通过被动的方式传递进来,而不用该对象主动创建或查找;
- 面向切面(AOP):支持面向切面编程,将应用业务逻辑层和系统服务层分开;
- 容器:包含并管理应用对象的配置以及生命周期,此时 Spring 就相当于一个容器;
- 框架集合:能将简单的组件进行配置,组合成为更为复杂的应用;在 Spring 中,应用对象被声明式地组合在一个 XML 文件中;此外,Spring 也提供了事务管理、 持久化框架集成等基础功能,将应用逻辑的开发留给开发者;
2. Spring 核心组件
Spring 是一个分层架构,主要由如下 7 大模块所构成。Spring 模块位于核心容器,定义了创建、配置和管理 Bean 的方式。
- Spring Core:提供 Spring 框架基本功能,主要组件是 BeanFactory,是工厂模式的实现,通过 IOC 机制将应用程序的配置和依赖性规范与实际的应用程序代码分开。
- Spring Context:一个配置文件,给 Spring 框架提供上下文信息,上下文包括 JNDI、EJB、电子邮件、国际化、校验和调度等企业服务。
- Spring AOP :通过配置管理特性,Spring AOP 直接将 AOP(面向切面)功能集成到 Spring 框架。从而我们能够十分方便的使用 Spring 框架来管理任何支持 AOP 的对象。模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用该组件,可以不依赖其他组件九江声明性事务管理集成到应用程序中。
- Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可以用来管理异常处理和不同数据库供应商抛出的错误信息。异常层次结构简化了错误处理,而且极大降低了需要编写的异常代码数量。Spring DAO 面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
- Spring ORM:Spring 框架中插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map,这些都遵从 Spring 的通用事务和 DAO 异常层次结构;
- Spring Web:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文,所以 Spring 框架支持与 Jakarta Structs 的集成。同时该模块还简化了处理多部分请求以及请求参数绑定到域对象的工作。
- Spring MVC:MVC 是一个全功能的构建 Web 应用的 MVC 实现,可以通过策略接口对 MVC 框架实现高度可配置。而且 MVC 还容纳了 JSP、Velocity、Tiles 等视图技术。
3. Spring 常用注解
4. IoC 原理
4.1 定义
Spring 通过一个配置文件来描述 Bean
之间的相互依赖关系,利用 Java 的反射功能来实例化 Bean
并建立 Bean
之间的依赖关系。Spring 的 IoC 容器在完成这些底层工作的基础上,还提供 Bean
实例缓存、生命周期管理、Bean
实例代理、事件发布、资源装载等高级服务;
总结而言:IOC 负责创建对象、管理对象(通过依赖注入)、整合对象、配置对象以及管理对象的生命周期;
4.2 Spring 容器高层视图
- Spring 启动时先读取
Bean
配置信息,并在 Spring 容器中生成一份对应的Bean
配置注册表; - 根据上一步中生成的
Bean
配置注册表来实例化Bean
,并装配好Bean
之间的依赖关系; - 将实例化后的
Bean
装载到 Spring 容器中的Bean
缓存池中,供上层的应用程序使用;
4.3 Spring Bean 的作用域及生命周期
4.3.1 作用域
Spring 中,用来组成应用程序的主体以及由 Spring IoC 容器所管理的对象叫做 Bean。简而言之,Bean 就是由 IoC 容器来进行初始化、装配和管理的对象。
Bean 的作用域主要有如下几种:
- Singleton(单例)
作用域为 Singleton
,该模式在多线程下不安全,表明 IoC 容器中只会存在一个共享 Bean 实例,而且所有对 Bean 的请求,主要 id
和该 Bean 定义相匹配,那么就会返回 Bean 的同一实例。Singleton
是单例模型,即在从创建容器的同时就会自动创建一个 Bean 的对象,无论是否使用,而且 每次获取到的对象都是同一对象。
- Prototype(原型):每次创建时使用
作用域为 Prototype
,表明一个 Bean 定义对应多个实例,该作用域中的 Bean 会导致在 每次对该 Bean 请求时均创建一个新的 Bean 实例。Prototype
是一个原型类型,在我们创建容器时并未实例化,而是当我们获取 Bean 时才去创建一个对象,而且每次获取到的对象都不一样。
- Request:一次 request 一个实例
作用域为 Request
,表明在一次 HTTP
请求中,容器返回该 Bean 的同一个实例,即每个 HTTP
请求均有各自的 Bean 实例,依据某个 Bean 定义创建而成,只在基于 Web 的 Spring ApplicationContext 情形下有效。当一次 HTTP
请求处理结束时,该作用域中的 Bean 实例均被销毁。
- Session
作用域为 Session
,表明 在一个 HTTP Session
中,容器返回该 Bean 的同一个实例,对不同的 Session
请求则创建新的实例,该 Bean
实例仅在当前 Session
内有效,只在基于 Web 的 Spring ApplicationContext 情形下有效。当一个 HTTP Session
被废弃时,在该作用域内的 Bean 也将失效。
4.3.2 生命周期
- Spring 对 Bean 进行实例化;
- Spring 将值和 Bean 的引用注入到 Bean 对应属性中;
- 若 Bean 实现了 BeanNameAware 接口,则 Spring 将 Bean 的 ID 传递给 setBeanName() 方法;
- 若 Bean 实现了 BeanFactoryAware 接口,Spring 将调用
setBeanFactory()
方法,将 Bean 所在应用引用传入进来; - 若 Bean 实现了 ApplicationContextAware 接口,Spring 将调用
setApplicationContext()
方法,将 Bean 所在应用的引用传入进来; - 若 Bean 实现了 BeanPostProcessor 接口,Spring 将调用
post-ProcessBeforeInitalization()
方法; - 若 Bean 实现了
InitializingBean
接口,Spring 将调用他们的after-PropertiesSet()
方法,类似地,如果 Bean 使用init-method
声明了初始化方法,则该方法也会被调用; - 若 Bean 实现了 BeanPostProcessor 接口,Spring 将调用他们的
post-ProcessAfterInitialization()
方法; - 此时,Bean 已经准备就绪,我们就可以被应用程序使用,他们将一直驻留在应用上下文中,直到该应用被销毁;
- 若 Bean 实现了 DisposableBean 接口,Spring 将调用它的
destory()
接口方法;同样,若 Bean 使用destroy-method
声明了销毁方法,该方法也将被调用;