这是我参与「第四届青训营 」笔记创作活动的第 8 天。今天复习了一下Spring的相关知识。
Spring是一个开源容器框架,可以接管web层,业务层,dao层,持久层的组件,并且可以配置各种bean,和维护bean与bean之间的关系。
其核心就是控制反转(IOC),和面向切面(AOP),简单的说就是一个分层的轻量级开源框架。
相关概念
Spring是一个分层架构,由7个定义良好的模块组成
- Spring core:提供了spring 的核心功能,BeanFactory是spring核心容器的主要组件,它通过Ioc把程序的配置和依赖性与实际的代码分开,是整个spring的基础
- Spring context:通过配置文件向spring提供上下文信息,它构建在BeanFactory之上,另外增加了国际化和资源访问等功能
- Spring dao:提供了一个简单有效的JDBC应用
- Spring aop:提供了面向方面编程的功能
- Spring orm:spring除了有自己的JDBC以外还提供了对其他ORM框架的支持,如Hibernate,都可以和spring进行良好的结合
- Spring web:提供了简化的处理多部分请求以及把请求参数绑定到域的任务。
- Spring MVC:提供了MVC2模式的实现,也可以和struts良好的集成在一起。
Spring并没有为我们提供日志系统,我们需要使用AOP(面向方面编程)的方式,借助Spring与日志系统log4j实现我们自己的日志系统。
三大核心组件
-
Core
-
Context
-
Beans(最核心)
-
调用Bean的方式
- 调用构造器
- 调用静态工厂方法
- 调用实例工厂方法
-
Bean五大作用域
| 作用域 | 描述 |
|---|---|
| singleton 单例模式 | 在Spring Loc中仅存在一个Bean实例,Bean以单例的形式存在,bean的默认作用域 |
| prototype 原型模式 | 一个bean定义对应多个对象实例,每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean()。 |
| request | 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于web的Spring WebApplicationContext环境。 |
| session | 同一个HTTP Session共享一个Bean,不同Session使用不同的Bean。 该作用域仅适用于web的Spring WebApplicationContext环境。 |
| application | 限定一个Bean的作用域为ServletContext的生命周期。 该作用域仅适用于web的Spring WebApplicationContext环境。 |
注意点
-
Web端特有的作用域:request 和 session是在Web开发才会存在
-
Serlet作用域:
-
Request域
-
Session域
- 范围:即一个会话(客户打开一个浏览器,发出各种请求,直到最后关闭该窗口)
- 作用:用来保存数据,数据保存在服务器端(与Cookie的区别)
-
ServletContext :
- 范围:包含该应用程序下所有的servlet和Request访问。
- 作用:实现数据的共享(一般为:数据库的url,密码,用户名等等)
-
额外:JSP的Page页面
- 范围:整个JSP页面
-
注意点
-
Spring容器:
-
无需手动创建Spring容器:使用spring的web应用时,不用手动创建spring容器,而是通过配置文件声明式地创建spring容器。
-
Bean:
-
bean同名问题:
- 一个应用程序中可以有多个spring容器 不同容器里的bean可以同名
- 但scope=application的时候,同名的bean只有一个
-
Spring不但可以管理Bean,还可以管理Bean的生命周期、作用域
-
-
Spring容器也叫IoC容器,本质上就是一个工厂。
-
IOC
是一种面向对象的设计思想,维护对象与对象之间的依赖关系,并且降低对象之间的耦合度。
注入方式
- 基于属性注入
- 就构造方法注入
- 基于setter注入
注解
-
@autowired
用于代表set方法,可以写在成员变量、set方法、构造器上。
-
属性
-
required
-
作用:对象是否可以为空
- false,对象可以为null;
- true,对象必须存对象,不能为null,找不到会抛出异常。
-
-
-
注意点
- 只能根据类型注入Bean。
- 首先根据类型找到对应的Bean, 如果对应类型的 Bean 不是唯一的,那么就根据属性名称和Bean的名称进行匹配。如果匹配得上,就会使用该Bean;如果还无法匹配,就会抛出异常。
-
@Resources
-
与@autowired
-
区别:
- 来源不同:@autowired 是Spring提供的,@resources由JDK提供(1.8后才有)
- 注入(装配)方式不同:@Autowired 默认按 byType 自动注入,不支持id匹配,(如果要,则需要加上@Qualifier注释); @Resource 默认按 byName 自动注入
-
相同点
-
属性:
- name 属性解析为 Bean 的名字
- type 属性则解析为 Bean 的类型。
-
都可以用来装配Bean
- 可以写在字段或者setter方法上
-
-
-
注意点:
-
匹配机制
- 如有指定的name属性,先按该属性进行byName方式查找装配;
- 其次再进行默认的byName方式进行装配;
- 如果以上都不成功,则按byType的方式自动装配。
- 都不成功,则报异常。
-
-
-
@Quanlifier
用于声明Bean的名称,
-
注意点
- 不能单独使用:需要加上value属性
- 补充:Autowired是根据类型自动装配的,加上@Qualifier则可以根据byName的方式自动装配
-
-
@Primary
会通知 Ioc 容器优先使用它所标注的Bean进行注入。
-
注意点:
- @Primary可以在多个类上标注,那就会抛异常
-
-
-
@Bean
- 作用:用于装配第三方Bean,适用于Bean
-
作用位置:
-
注意点:
- 需要在@Configuration注解下创建,但不是必须的它也可以出现在带有@Component注解的类中,甚至是普通的类中
-
AOP
Spring采用依赖注入的方式,实现了Ioc思想
术语解释
-
接入点(Join point) :程序执行的某个特定位置。 (一个类或者一段代码拥有一些具有边界性质的特定点)
- 例如:如一个类的初始化前后,或者类的某个方法调用前后、方法抛出异常后等等;
- 注意点:Spring仅支持方法的连接点,即仅能在方法调用前后、方法抛出异常时这些程序执行点织入增强。
-
切点(Pointcut) :切入点是一个连接点的过滤条件。
-
UserService类中的所有方法实际上都是连接点,即连接点是程序类中客观存在的事物
-
注意点:
- AOP通过切点(筛选条件)定位到特定的连接点
- 一个切点匹配多个连接点
- 每个类都拥有多个连接点
-
-
通知(Advice,又称"增强") :
- 定义:切面在某个具体额连接点采取的行为或行动。 (即自己想要的功能,安全,事务,日志)
- 注意点:它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。
-
通知器(Advisor)
- 定义:由一个切入点和一个通知组成。
-
切面(Aspect) :
- 定义:同样是切点和通知组成。
- Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
-
引入(Introduction) :
- 定义:允许我们向现有的类添加新方法属性。把切面(也就是新方法属性:通知定义的)用到目标类中吗
-
目标对象(Target object) :被通知的对象(方法)
-
代理(proxy) :向目标对象应用通知之后创建的对象(看"代理"本身的字面意思)
-
织入(Weaving) :
-
把切面应用到目标对象来创建新的代理对象的过程。
-
注意点:
- Spring通过运行时的方式来创建新的代理对象
-
织入
织入是将增强添加对目标类具体连接点上的过程。AOP像一台织布机,将目标类、增强或引介通过AOP这台织布机天衣无缝地编织到一起
时间
-
编译期织入,这要求使用特殊的Java编译器。
-
类装载期织入,这要求使用特殊的类装载器。
-
动态代理织入,
-
JDK动态代理(AOP默认使用)
- Java提供的动态代理技术,可以在运行时创建接口的代理实例
-
GGLib动态代理,
- 采用底层的字节码技术,在运行时创建子类代理的实例
- 当目标对象不存在接口时,Spring AOP就会采用这种方式,在子类实例中织入代码。
-
注意点
-
运行时注入
- 需要为目标生成代理对象
通知类型
- 前置通知:在连接点前面执行,前置通知不会影响连接点的执行,除非此处抛出异常。正常返回通知
- 后置通知:连接点正常执行完成后执行,如果连接点抛出异常,则不会执行。 异常返回通知
- 环绕通知:环绕通知围绕在连接点前后,比如一个方法调用的前后。这是最强大的通知类型,能在方法调用前后自定义一些操作。 环绕通知还需要负责决定是继续处理join point(调用ProceedingJoinPoint的proceed方法)还是中断执行。
- 返回(最终)通知:在连接点执行完成后执行,不管是正常执行完成,还是抛出异常,都会执行返回通知中的内容。
- 异常通知:在目标方法抛出异常时执行的通知。
通知顺序
-
在目标方法没有抛出异常的情况下
- 前置通知
- 环绕通知的调用目标方法之前的代码
- 目标方法
- 环绕通知的调用目标方法之后的代码
- 后置通知
- 最终通知
-
在目标方法抛出异常的情况下
- 前置通知
- 环绕通知的调用目标方法之前的代码
- 目标方法
- 抛出异常
- 异常通知
- 最终通知
注解
- @Controller
类
-
BeanFactory和FactoryBean
-
BeanFactory
-
工厂Bean,是一个Bean,作用是产生其他bean 实例
-
作用:
- 产生其他bean 实例,实现单例模式
- 提供一个工厂方法,该方法用来返回其他Bean 实例
-
方法:
- getBean(string name):从Spring容器中获取对应Bean对象的方法
- containsBean(String name)::用于判断Spring容器中是否存在该对象
- isSingleton(String name):用于判断Bean对象是否为单例对象。
-
注意
- 通常情况下,Bean 无须自己实现工厂模式,Spring 容器担任工厂角色
- 但少数情况下,容器中的Bean 本身就是工厂,其作用是产生其它Bean 实
-
-
FactoryBean
-
Bean 工厂,是一个工厂(Factory)
-
顶层接口:Spring IOC 容器的最顶层接口就是这个
-
作用:
- 管理Bean
- 即实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
-
-
-
ApplicationContext
- 作用:提供框架的实现,包括BeanFactory的所有功能
-
BeanWrapper
- 作用:提供统一的get以set方法,对Bean的包装
-
其他
-
SpringFactoriesLoader
- 该类并不对外暴露给应用开发者使用,而是Spring框架自己使用的内部工具类,本身被声明为抽象类(abstract),不可以被实例化。
-
\