文章目录
spring框架
资料官方学习网站地址:https://spring.io/
1.概念
Spring是一个轻量级的Java开源框架,它是为了解决企业应用开发的复杂性而创建的,即简化Java开发。
1.核心
Spring的核心是控制反转(IoC)和面向切面编程(AOP)。通过IOC容器管理POJO或JavaBean对象,以及它们之间的耦合关系;通过AOP以动态非入侵的方式增强服务。
2.优点
-
轻量级的
Spring框架使用的jar都比较小,一般在1M一下或者几百KB,Spring核心功能的所需的jar总共在3M左右。Spring框架运行占用的资源少,运行效率高。
-
非侵入式
编写一些业务类的时候不需要继承Spring特定的类,通过配置完成依赖注入后就可以使用,此时,Spring就没有侵入到业务类的代码里。
-
方便解耦,简化开发
Spring就是一个大工厂,可以将所有对象创建和依赖关系维护,交给Spring管理。
-
控制反转(IOC)
Spring提供了Ioc控制反转,由容器管理对象,对象的依赖关系。原来在程序代码中的对象创建方式,现在由容器完成。对象之间的依赖解耦合。
-
AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付在Spring中,开发人员可以从繁杂的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
-
声明式事务的支持
Spring提供了容器功能,容器可以管理对象的生命周期、对象与对象间的关系、我们可以通过编写XML来设置对象关系和初始值,这样容器在启动后,所有对象都直接可以使用,不用编写任何编码来产生对象。Spring有两种不同的容器:Bean工厂以及应用上下文。
-
方便集成各种优秀的框架
可以将简单的组件配置,组成复杂的应用,Spring也提供了很多基础功能(事务管理,持久化框架集成,数据访问,web)将应用逻辑留给开发者。
-
降低JavaEE API使用难度
Spring对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低。
3.缺点
1.Spring依赖反射,反射影响性能
如何避免?
- 不要频繁地使用反射,大量地使用反射会带来性能问题。
- 通过反射直接访问实例会比访问方法快很多,所以应该优先采用访问实例的方式。
2.使用门槛高,入门需要较长时间。
2.Spring体系结构
-
Core Container(核心容器)
Beans:管理Beans
Core:Spring核心
Context:配置文件
ExpressionLanguage:SpEL表达式
-
AOP(切面编程)
-
AOP框架:Aspects
-
Data Access(数据库整合)
JDBC,ORM,OXM,JMS,Transaction
-
Web(MVC Web开发)
Web,Servlet,Portlet,Struts
-
Test(Junit整合)
3.Spring Hello World 搭建
-
Maven导入Spring核心基础jar
<!-- spring-context 自动加载spring核心功能所需的jar--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.2.RELEASE</version> </dependency>
-
编写Spring配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--将Java中类交给spring管理 由spring容器生成对象。--> <bean id="user" class="com.ff.spring.bean.User"> </bean> </beans>
-
测试
编写一个User实体类
public class User { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
测试Spring
import com.ff.spring.bean.User; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test1 { @Test public void test() { /* 之前编码方式,需要一个对象的时候,在代码中自己new一个 */ /*User user = new User();*/ /* IOC 控制反转 反转控制 在程序中不需要我们主动区创建对象,而是由spring框架创建并管理 */ //加载spring配置文件,启动spring框架(spring容器) ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); User user1 = (User)applicationContext.getBean("user"); System.out.println(user1); User user2 = (User)applicationContext.getBean("user"); System.out.println(user2); } } //结果 /*User{name='null', age=0} User{name='null', age=0}*/
4.IOC(控制反转)
控制反转(IOC)是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。
IOC容器是具有依赖注入功能的容器,负责对象的实例化、对象的初始化,对象和对象之间依赖关系配置、对象的销毁、对外提供对象的查找等操作,对象的整个生命周期都是由容器来控制。我们需要使用的对象都由IOC容器进行管理,不需要我们再去手动通过new的方式去创建对象,由IOC容器直接帮我们组装好,当我们需要使用的时候直接从IOC容器中直接获取就可以了。
正控:若要使用某个对象,需要自己去负责对象的创建。
反控:若要使用某个对象,只需要从Spring容器中获取需要使用的对象,不关心对象的创建过程,也就是把创建对象的控制权反转给了Spring框架。
目的:降低耦合度。
底层实现方式:解析xml/扫描注解标签+工厂模式+反射机制
控制反转是一种通过描述(XML或注解)并通过第三方去生成或获取特定对象的方式。在Spring中实现控制反转的是IOC容器,其实现方式是依赖注入(DI)。
1.作用:
- 管理对象的创建和依赖关系的维护。
- 解耦降低了依赖,由容器去维护具体的对象的创建。
- bean对象生命周期管理。
2.使用IOC容器的优点:
- IOC和DI的配合使用能把应用的实际代码降到最低。
- sprng集成了自己的测试模块,无需依赖于junit。
- IOC容器支持立即加载和延迟加载(懒加载)。
3.spring IOC支持哪些功能
- 依赖注入
- 依赖检查
- 自动装配
- 支持集合
4.依赖注入(DI)
**概念:**组件之间依赖关系由容器在运行期间决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。通过依赖注入机制,只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,有谁实现。
**目的:**提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。
-
set注入:容器通过调用无参构造器或无参static工厂方法实例化bean之后,调用该bean的setter方法,即实现了基于setter的依赖注入。
xml配置如下
-
构造器注入:通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖。
xml配置如下
-
静态工厂方法注入
xml配置如下
-
实例工厂方法
xml配置如下
5.面向切面编程(aop)
1.什么是AOP?
AOP技术利用一种称为”横切“的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到应该可重用模块,并将其命名为”Aspect“,即方面。所谓”方面“,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。使用“横切”技术,AOP 把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。
Aop 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
6.事务
概念
事务可以看做是由对数据库若干操作组成的一个单元。
我们在开发企业应用时,对于业务人员的一个操作实际是对数据读写的多步操作的结合。由于数据操作在顺序执行的过程中,任何一步操作都有可能发生异常,异常会导致后续操作无法完成,此时由于业务逻辑并未正确的完成,之前成功操作数据的并不可靠,需要在这种情况下进行回退。
事务的作用:就是为了保证用户的每一个操作都是可靠的,事务中的每一步都必须成功执行,只要有发生异常就回退到事务开始未进行操作的状态,这些操作要么都完成,要么都取消,从而保证数据满足一致性的要求。
事务特征(ACID)
- 原子性
- 一致性
- 隔离性
- 持久性
spring中事务管理分为两种形式
-
编程式事务
在项目中很少使用,需要注入一个事务管理对象TransactionTemplate,然后在我们代码中需要提交事务或回滚事务时自己写代码实现。
-
声明式事务
管理建立在AOP基础上,本质是对方法前后进行拦截,所以声明式事务是方法级别的。
管理方式:
- 基于xml配置
- 基于注解实现
事务传播行为
什么是事务传播行为?
指的是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。例如:methodA事务方法调用methodB事务方法时,methodB是继续在调用者methodA的事务中运行呢,还是为自己开启一个新事务运行,这就是由methodB的事务传播行为决定的。
伪代码:
public void methodA(){
methodB();
//doSomething
}
@Transaction(Propagation=XXX)
public void methodB(){
//doSomething
}
代码中methodA()方法嵌套了methodB()方法,methodB()的事务传播行为由@Transaction(Propagation=XXX)设置决定。这里需要注意methodA()并没有开启事务,某一个事务传播行为修饰的方法并不是必须要在开启事务的外围方法中调用。
事务传播行为是spring框架独有的事务增强特性,不属于事务实际提供方数据库行为。
spring定义了七种传播行为:
事务传播行为类型 | 说明 |
---|---|
PROPAGATION_REQUIRED | 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。 |
PROPAGATION_SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
PROPAGATION_MANDATORY | 使用当前的事务,如果当前没有事务,就抛出异常。 |
PROPAGATION_REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务挂起。 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
PROPAGATION_NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 |
主要:
-
PROPAGATION_REQUIRED
指定的方法必须在事务内执行,若当前存在事务,加入当前事务中,若当前没有事务,则创建一个新事务,这种传播行为最常见,也是spring默认的传播事务。
-
PROPAGATION_SUPPORTS
支持当前事务,如果当前没有事务,就以非事务方式执行。
-
PROPAGATION_REQUIRES_NEW
总是新建一个事务,如果当前存在事务,把当前事务挂起,知道新建的事务结束。