Spring框架
1、Spring的作用
Spring用于整合一切优秀资源,然后对外提供一个统一的服务。管理软件中的对象,即创建对象和维护对象之间的关系。
整合全部的第三方框架,让程序调用浑然一体。
2、为什么要使用Spring(Spring的优点)
1)轻量级开发框架,简化开发。
2)IOC与AOP的应用,解耦,便于维护和升级。
通过spring提供的IOC容器,可以将对象间的依赖关系交由spring进行控制,避免硬编码造成的过度耦合;
通过AOP功能,方便进行切面编程,如性能检测、事务管理、日志记录。
3)可容易的与第三方框架进行整合应用,方便集成各种优秀的框架。
4)声明式事务的支持。
5)降低JavaEE API的使用难度,对JDBC,JavaMail,远程调用进行了简便的封装。
3、Spring架构
Spring模块构建在核心容器之上,核心容器定义了创建、配置与管理bean方式。
组成Spring的每一个模块都可以单独存在,或者与其他一个或多个模块联合实现。
spring核心模块3.1 组成模块
3.2 核心组件
3.2.1 BeanFactory
创建bean的工厂。
3.2.2 ApplicationContext
外部应用程序调用,也是Spring容器的上下文。两个核心读取对象(ClassPathXMLApplicationContext、AnnotationApplicationContext)。
3.2.3 IOC控制反转
Inversion of Control。开发者无需自己new对象,无需关心对象的创建过程,将对象的创建,对象的存储(map),对象的管理(依赖查找,依赖注入)交给了spring容器,只需在配置文件里面添加相应的bean标签配置即可。
手动创建对象: User user = new User();
容器创建对象:
1-入口类读取配置文件:
ClassPathXmlApplicationContext context = new ClassPathXMLApplicationContext(“spring配置文件的名字”);
2-通过spring配置文件里面的id取到对应的类,spring会自动为其创建相应的实例对象。
User user = context.getBean(user);
单例对象
Spring中默认Bean对象的作用域为单例,也可以在配置文件中通过scope属性或使用相关注解为其指定作用域。
Singleton:单实例,默认值。这个作用域标识的对象具备全局唯一性。Spring IOC容器只会创建该bean定义的唯一实例,即整个Spring IOC容器中只会创建当前类的唯一一个对象。
Singleton负责对象的创建、初始化、销毁。
单实例节省空间、占用内存小,但可能存在线程安全问题,所以适用于对象不含可变状态时。
1)程序启动时(Tomcat)加载Spring,Spring根据包扫描xml实例化对象;
2)基于反射调用无参构造方法实例化对象;
3)周期:与容器共生死
多例对象
Prototype:多实例。该作用域标识的对象每次获取都会创建新的对象。Spring IOC容器会在每一次获取当前bean时都产生一个新的bean实例。
prototype只负责对象的创建和初始化,不负责销毁。
多例对象线程安全,适用于对象含可变的状态。
1) 适用场景:获取第三方连接时;
2)程序调用时新建,线程结束时销毁。(服务器、框架、数据库只有一个,但有多份连接);
IOC的核心是对象生命周期管理(资源管理)以及依赖注入(资源协同);
3.2.4 DI依赖注入(装配过程)
Dependency Injection.松耦合方式实现对象的直接依赖。
所谓DI就是在创建对象的同时或之后,如何给对象的属性赋值。组件之间的依赖关系由容器在应用系统运行期来决定,也就是由容器动态地将某种依赖关系的目标对象实例注入到应用系统的各个关联组件之中。
Spring提供的两种注入方式
1)set注入
普通属性的注入;
对象属性的注入;
2)构造注入(使用最多)
通过配置文件注入时,name属性的值必须与构造函数中参数的名字相同。
普通属性直接通过value注入,对象属性通过ref属性注入。
当有多个实现类时需要加@Qualifier(“实现类”)指明当前使用的实现类。
3)Spring的自动装配方式(@Autowired)
1-ByName
(配置文件)把与bean属性具有相同名字的其他bean自动装配到bean的对应属 性中。【属性名称和bean的名称可以对应】。有点类似于set注入。 autowire=“byName”
2-ByType
(配置文件)不使用属性名称对应,选择使用类型来自动装配。也类似与set注入 。autowire=“byType”
3-constructor
构造注入
@Autowired
默认是按照类型(ByType)来自动装配属性,若匹配到类型的多个实例再通过 ByName来装配。(通过@Qualifier指明是哪一个)。若通过ByName还确定不了,则可以通过@Primary与@Priority注解来确定。
4)spring如何管理对象?
spring容器内部维护了一个超大map<ID,实例对象>
spring共有2种管理对象的方式:
1)xml配置文件。spring启动,加载配置文件;程序解析配置文件,加载bean对象,根据class类型利用反射机制调用无参构造实例化对象,即Map<bean的id,对象>。
2)注解方式。配置包扫描,获取注解标识的class,利用反射机制调用无参构造实例化对象,将数据保存到spring容器中。
控制反转(IOC)和依赖注入(DI)分不开,二者有着密不可分的关系。
IOC将对象的创建交给Spring,spring创建好该对象后就把它(自动装配)注入到相应的引用对象中使用。
3.2.5 AOP面向切面编程
补充java面向对象的不足,扩展功能。比如日志,异常处理,事务处理、缓存处理等。
AOP基于OCP(开闭原则)在不改变原有系统核心业务代码的基础上动态添加一些扩展功能并可以控制对象的执行(例如权限控制)。
开闭原则:在不改变原有的功能的基础上,对业务功能进行扩展。
1)AOP底层基于代理机制实现功能扩展(代理机制)
A: JDK代理。假如目标对象(被代理对象)实现接口,则底层默认采用JDK动态代理机制为目标对象创建代理对象(目标类和代理类会实现共同接口);
B:CGLIB代理。假如目标对象(被代理对象)没有实现接口,则底层默认采用CGLIB代理机制为目标对象创建代理对象(默认创建的代理类会继承目标对象类)。
2)AOP相关术语与注解
A: 切面(aspect):横切面对象,一般为一个具体类对象(使用@Aspect标识)。
切面主要由两部分组成:切入点+功能增强(通知)。
B: 连接点(JoinPoint):程序执行过程中某个特定的点,一般指拦截到的方法。
C: 切入点(PointCut): 对连接点拦截内容的一种定义,一般可以理解为多个连接点的结合。
spring中通过切入点表达式定义具体切入点,其常用AOP切入点表达式有:
粗粒度控制:bean(类级别),within(类级别)。
细粒度控制:execution(方法级别),@annotation(方法级别)
execution(返回值类型 包名.类名.方法名(参数列表))
D: 通知(Advice)【五种类型】:在切面的某个特定连接点上执行的动作(扩展功能)。细粒度控制::
@Around用于定义一个环绕通知(满足切入点表达式的核心业务方法执行之前和执行之后的一个操作)。
1)前置通知(@Before):方法执行之前执行
2)返回通知(@AfterReturnning):方法return之后执行
3)异常通知(@AfterThrowing):方法出现异常之后执行
4)后置通知(@After):又称为最终通知(finally)
5)环绕通知(@Around)【重点】
结构:
Try{
@Before
核心业务
@AfterReturnning
}catch(Exception e){
@AfterThrowing
}finally{
@After
}
若以上四个一起使用则可以使用@Around环绕通知去替换。
核心业务正常结束时:若有after,先执行after,再执行returnning。
核心业务出现异常时:若有after,先执行after,再执行thowing。
切入点可以有多个,而连接点只能有一个。
3.2.6 事务管理
1)编程式事务
通过编程的方式实现事务。
2)声明式事务(使用较多)
基于AOP,将具体业务逻辑与事务处理解耦。声明式事务管理使业务代码逻辑不受污染,所以实际使用中常用这种方式。以下是声明式事务处理的两种方式。
A: 配置文件中做相关事务规则声明。
B: 基于@Transaction注解方式。
timeout:事务超时时间,默认值为-1,表示未超时。若配置了具体时间,超过该时间还没完成事务,则自动回滚。
read-only: 执行事务为只读事务。
rollback-for:指定能够触发事务回滚的异常类型。
no-rollback-for:抛出no-rollback-for指定的异常类型,不回滚事务。
propagation:事物的传播行为,默认值为required。
isolation:事务的隔离度。
@Transactional注解可以用在方法上也可以添加到类级别上。当把@Transactional 注解放在类级别时,表示所有该类的公共方法都配置相同的事务属性信息。当类级别配置了@Transactional,方法级别也配置了@Transactional,应用程序会以方法级别的事务属性信息来管理事务,换言之,方法级别的事务属性信息会覆盖类级别的相关配置信息。
3)事务的隔离级别
A: READ_UNCOMMITTED (此级别可能会出现脏读)
B : READ_COMMITTED(此级别可能会出现不可重复读)
C : REPEATABLE_READ(此级别可能会出现幻读)
D : SERIALIZABLE(多事务串行执行)
spring中一般采用 @Transactional(isolation=Isolation.READ_COMMITTED) 方式声明级别, 这种方式是并发性能和安全性折中的选择. 是大多数软件项目采用的隔离级别.
4) 事务的传播特性
4、Spring架构分析
4.1 配置基础架构
4.2 IOC API基础架构
4.3 IOC模块核心
4.3.1 Spring Bean容器的初始化
1)资源加载器读入spring配置文件信息;(若是使用注解方式的话,则通过反射获取类的信息,再根据其无参构造实例化bean)。
2)通过Bean定义阅读器阅读bean定义信息交由Map管理,Map<String, BeanDefinition>;
3)bean工厂再根据其bean定义信息产生beanId对应的bean对象实例。
4.3.2 Spring中的两大map对象
1)一个map用于存储bean的配置信息;(基于XML配置文件实现)
2)一个map用于存储bean的实例信息;
4.3.3 Spring中两大bean对象
Bean对象的创建
1)未实现FactoryBean接口(直接构造方法)
2)实现FactoryBean接口(调用FactoryBean对象的getObject方法)
4.4.4 两大Bean对象的描述方式
1)XML方式(例如<bean id=”factory” class=”com.beans.Factory”>)
2)annotation方式
上面无论是哪一个注解,对Spring来说都认为是一样的bean。