Spring
2021-12-28 10:29:19 69 举报
AI智能生成
spring核心技术IOC、AOP、事务、整合mybatis
作者其他创作
大纲/内容
框架前言
框架怎么学
框架是一个软件
1、知道框架能做什么,mybatis--访问数据库,对表中数据执行CRUD
2、框架的语法,框架要完成一个功能,需要一定的步骤支持。
3、工作两三年后,框架的内部实现,框架内部怎么做,原理是什么。
4、通过学习,可以实现一个框架。
1、知道框架能做什么,mybatis--访问数据库,对表中数据执行CRUD
2、框架的语法,框架要完成一个功能,需要一定的步骤支持。
3、工作两三年后,框架的内部实现,框架内部怎么做,原理是什么。
4、通过学习,可以实现一个框架。
SSH:Struct2+Spring+Hibernate(全自动)
SSM:SpringMVC(将前端数据传给后台)+Spring(容器框架)+Mybatis(半自动持久层框架)
SSJ:Spring+SpringMVC+SpringJDBC
SSM:SpringMVC(将前端数据传给后台)+Spring(容器框架)+Mybatis(半自动持久层框架)
SSJ:Spring+SpringMVC+SpringJDBC
Spring Boot:一个快速开发的脚手架,基于SpringBoot可以快速的开发单个微服务。
约定大于配置!
学习SpringBoot的前提,需要完全掌握Spring和SpringMVC!承上启下的作用!
Spring Cloud:是基于SpringBoot实现的,大多数公司都在使用SpringBoot进行快速开发。
约定大于配置!
学习SpringBoot的前提,需要完全掌握Spring和SpringMVC!承上启下的作用!
Spring Cloud:是基于SpringBoot实现的,大多数公司都在使用SpringBoot进行快速开发。
简介
Spring(创始人:Rod Johnson )最早:interface21框架
Spring:开源免费的、轻量级的、非侵入式的容器(一个服务器软件,一个框架)!
类与类之间的管理,帮助开发人员创建对象,管理对象间的关系。
Spring:开源免费的、轻量级的、非侵入式的容器(一个服务器软件,一个框架)!
类与类之间的管理,帮助开发人员创建对象,管理对象间的关系。
依赖:class a中使用class b的属性或方法,叫class a依赖class b
注:maven管理外部依赖,spring管理项目内部依赖
注:maven管理外部依赖,spring管理项目内部依赖
什么是spring
是一个框架,核心技术是ioc、aop,能实现那模块之间,类之间的解耦合。
Spring的优势
1、轻量:Spring核心功能所需的jar总共3M左右
2、针对接口编程,解耦合
通过Spring提供的IOC容器,可以将对象间的依赖关系交由Spring控制,避免硬编码造成的过度耦合。用户也不必为单例模式类、属性文件解析等底层需求编写代码,可以更专注于上层的应用。
3、AOP编程的支持
通过Spring的AOP功能,方便进行面向切面编程,许多不容易用传统OOP实现的功能可以通过AOP轻松实现。
4、方便集成各种优秀框架
2、针对接口编程,解耦合
通过Spring提供的IOC容器,可以将对象间的依赖关系交由Spring控制,避免硬编码造成的过度耦合。用户也不必为单例模式类、属性文件解析等底层需求编写代码,可以更专注于上层的应用。
3、AOP编程的支持
通过Spring的AOP功能,方便进行面向切面编程,许多不容易用传统OOP实现的功能可以通过AOP轻松实现。
4、方便集成各种优秀框架
什么样的对象放入到容器中
dao类、service类、controller类、工具类
spring中的对象默认都是单例的,在容器中叫这个名称的对象只有一个
Spring容器中的bean可以分为5个范围:
(1)singleton:默认,每个容器中只有一个bean的实例,单例的模式由BeanFactory自身来维护。
(2)prototype:为每一个bean请求提供一个实例。
(3)request:为每一个网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。
(4)session:与request范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。
(5)global-session:全局作用域,global-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。全局作用域与Servlet中的session作用域效果相同。
(1)singleton:默认,每个容器中只有一个bean的实例,单例的模式由BeanFactory自身来维护。
(2)prototype:为每一个bean请求提供一个实例。
(3)request:为每一个网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。
(4)session:与request范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。
(5)global-session:全局作用域,global-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。全局作用域与Servlet中的session作用域效果相同。
不放到spring容器的对象
实体类对象,实体类数据来自数据库的
servlet,listener,filter等
怎么使用spring
spring是一个容器,把项目中用的对象放到容器中
1、使用xml配置文件,使用<bean>
2、注解
xml与注解的区别
xml更加万能,适用于任何场合,维护简单方便。
注解不是自己类使用不了,维护相对复杂。
注解不是自己类使用不了,维护相对复杂。
xml与注解最佳实践
xml用来管理bean;
注解只负责完成属性的注入。
注解只负责完成属性的注入。
实际应用
注解为主,配置文件为辅
让容器完成对象的创建,对象之间关系的管理(属性赋值)
我们在程序中获取 要使用的对象
使用spring框架的步骤
1、加入spring-context依赖(间接加入了spring-aop依赖)
<!--IOC-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.13</version>
</dependency>
<!--IOC-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.13</version>
</dependency>
2、创建类:接口,实现类,没有接口的类
3、创建spring的配置文件,使用<bean>声明对象
4、使用容器中的对象,通过ApplicationContext接口和它的实现类
ClassPathXmlApplicationContext的方法getBean()
ClassPathXmlApplicationContext的方法getBean()
核心技术
IOC(Inversion of Controller)(控制反转)
控制反转是一个理论,概念,思想。
描述的:把对象的创建,赋值,管理工作都交给代码之外的容器实现,也就是对象的创建是其它外部资源完成。
控制:创建对象,对象的属性赋值,对象之间的关系管理。
反转:把原来的开发人员管理,创建对象的权限转移给代码之外的容器实现。由容
器代替开发人员管理对象。创建对象,给属性赋值。
正转:由开发人员在代码中使用new构造方法创建对象,开发人员主动管理对象。
psmv(String args){
Student stu=new Student(); //在代码中创建对象,正转
}
描述的:把对象的创建,赋值,管理工作都交给代码之外的容器实现,也就是对象的创建是其它外部资源完成。
控制:创建对象,对象的属性赋值,对象之间的关系管理。
反转:把原来的开发人员管理,创建对象的权限转移给代码之外的容器实现。由容
器代替开发人员管理对象。创建对象,给属性赋值。
正转:由开发人员在代码中使用new构造方法创建对象,开发人员主动管理对象。
psmv(String args){
Student stu=new Student(); //在代码中创建对象,正转
}
IOC由Spring来创建,管理,装配,IOC就是典型的工厂模式,通过sessionFactory去注入实例。
为什么使用IOC
目的是减少对代码的改动,也能实现不同的功能,实现业务对象之间的解耦合。
例如:能实现service和dao对象之间的解耦合。
例如:能实现service和dao对象之间的解耦合。
java中创建对象有哪些方式
1、构造方法,new Student()
2、反射
3、序列化
4、克隆
5、动态代理
6、IOC:容器创建对象
2、反射
3、序列化
4、克隆
5、动态代理
6、IOC:容器创建对象
IOC的体现
servlet
1、创建类继承HttpServlet
2、在web.xml注册servlet,
使用<servlet-name>myservlet</servlet-name>
<servlet-class>com.kx.controller.MyServlet</servlet-class>
3、未创建Servlet对象,没有MyServlet myservlet=new MyServlet()
4、Servlet是Tomcat服务器给你创建的。Tomcat也叫容器
Tomcat作为容器:里面存放的有Servlet对象,Listener,Filter对象
1、创建类继承HttpServlet
2、在web.xml注册servlet,
使用<servlet-name>myservlet</servlet-name>
<servlet-class>com.kx.controller.MyServlet</servlet-class>
3、未创建Servlet对象,没有MyServlet myservlet=new MyServlet()
4、Servlet是Tomcat服务器给你创建的。Tomcat也叫容器
Tomcat作为容器:里面存放的有Servlet对象,Listener,Filter对象
IOC的技术实现
DI(Dependency Injection依赖注入)是IOC的技术实现。
DI:只需要在程序中提供要使用的对象名称即可,至于对象如何在容器中创
建,赋值,查找都有容器内部实现。
依赖:bean对象的创建依赖于容器。
注入:bean对象中的所有属性,由容器来注入
DI:只需要在程序中提供要使用的对象名称即可,至于对象如何在容器中创
建,赋值,查找都有容器内部实现。
依赖:bean对象的创建依赖于容器。
注入:bean对象中的所有属性,由容器来注入
DI给属性赋值
一个类中的属性:简单类型、对象类型、集合类型
1、属性注入(set注入)(*):spring调用类的set方法实现属性赋值
1、简单类型的set注入
<property name="属性名" value="属性值">
<property name="属性名" value="属性值">
例:
<--
id:bean的唯一标识符,也就是相当于我们学的对象名
class:bean对象所对应的全限定名:包名+类型
name:也就是别名,而且name可以同时取多个别名
-->
<bean name="car1,car2" class="com.kx.beans.Car" >
<property name="brand" value="suv"/>
</bean>
<--
id:bean的唯一标识符,也就是相当于我们学的对象名
class:bean对象所对应的全限定名:包名+类型
name:也就是别名,而且name可以同时取多个别名
-->
<bean name="car1,car2" class="com.kx.beans.Car" >
<property name="brand" value="suv"/>
</bean>
2、引用类型的set注入
<property name="属性名" ref="bean的id">
<property name="属性名" ref="bean的id">
例:
<bean name="person" class="com.kx.beans.Person">
<property name="name" value="zhangsan"/>
<property name="age" value="18"/>
<property name="car" ref="car"/>
</bean>
<bean name="person" class="com.kx.beans.Person">
<property name="name" value="zhangsan"/>
<property name="age" value="18"/>
<property name="car" ref="car"/>
</bean>
<!--内部bean-->
<bean name="person1" class="com.kx.beans.Person">
<property name="name" value="zhnagsan"/>
<property name="age" value="18"/>
<property name="car">
<bean class="com.kx.beans.Car">
<property name="brand" value="suv"/>
<property name="crop" value="浙江"/>
<property name="price" value="100000"/>
<property name="maxSpeed" value="30"/>
</bean>
</property>
</bean>
<bean name="person1" class="com.kx.beans.Person">
<property name="name" value="zhnagsan"/>
<property name="age" value="18"/>
<property name="car">
<bean class="com.kx.beans.Car">
<property name="brand" value="suv"/>
<property name="crop" value="浙江"/>
<property name="price" value="100000"/>
<property name="maxSpeed" value="30"/>
</bean>
</property>
</bean>
<!--级联属性--><!--级联属性配置:Car中要有set get方法-->
<bean name="person2" class="com.kx.beans.Person">
<property name="name" value="zhangsan"/>
<property name="age" value="18"/>
<property name="car" ref="car"/>
<property name="car.maxSpeed" value="230"/>
</bean>
<bean name="person2" class="com.kx.beans.Person">
<property name="name" value="zhangsan"/>
<property name="age" value="18"/>
<property name="car" ref="car"/>
<property name="car.maxSpeed" value="230"/>
</bean>
2、构造注入(如果写了带参构造器,必须写出无参构造):spring调用有参构造方法
1、<constructor-arg>的name属性,name表示构造方法的形参名
例:
<!--构造器注入-->
<bean name="car" class="com.kx.beans.Car">
<constructor-arg name="brand" value="audi"/>
<constructor-arg name="crop" > //字面值
<!--cdata特殊字符-->
<value><![CDATA[<上海>]]></value>
</constructor-arg>
<constructor-arg name="price" value="200000"/>
</bean>
<!--构造器注入-->
<bean name="car" class="com.kx.beans.Car">
<constructor-arg name="brand" value="audi"/>
<constructor-arg name="crop" > //字面值
<!--cdata特殊字符-->
<value><![CDATA[<上海>]]></value>
</constructor-arg>
<constructor-arg name="price" value="200000"/>
</bean>
2、<constructor-arg>的index属性,表示构造方法形参的位置,从0开始
3、自动注入
由spring根据某些规则,给引用类型完成赋值,常用的由byName,byType
1、byName:按名称注入,java类中引用类型的属性名和spring容器中bean的【id】一样,
数据类型一样,这样bean赋值给引用类型
数据类型一样,这样bean赋值给引用类型
2、byType:按类型注入,Java类中引用类型的是【数据类型】和spring容器中的【class】是同源关系的,
这样bean就能赋值给引用类型
这样bean就能赋值给引用类型
Spring是使用的DI实现了IOC的功能,Spring底层创建对象,使用的是反射机制。
常用注解
注解的使用步骤
1、加入依赖:spring-context,间接加入spring-aop
2、在类中加入注解
3、在spring的配置文件中,加入组件扫描器的标签<context:component-scan base-package="包名">
1、@Component:标识了一个受Spring管理的组件,有几个衍生注解,在web开
发中,会按照mvc三层架构分层。
2、@Repository:dao对象,用来访问数据库
3、@Service
4、@Controller
5、@Value:简单类型的属性赋值
发中,会按照mvc三层架构分层。
2、@Repository:dao对象,用来访问数据库
3、@Service
4、@Controller
5、@Value:简单类型的属性赋值
6、@Autowired:引用类型的赋值,byType。
如果需要自动装配上名字属性,则需要通过@Qualifier(value="xxx")
如果需要自动装配上名字属性,则需要通过@Qualifier(value="xxx")
使用:
直接在属性上使用即可!也可以在实体类set方法上使用!
使用Autowired可以不用编写Set方法了,前提是这个自动装配的属性在IOC(Spring)容器中存在
,且符合byName。
直接在属性上使用即可!也可以在实体类set方法上使用!
使用Autowired可以不用编写Set方法了,前提是这个自动装配的属性在IOC(Spring)容器中存在
,且符合byName。
例:
@Autowired(required = false)说明这个对象可以为null,否则为空。
@Qualifier(value = "jemi")
private Cat cat;
@Autowired(required = false)说明这个对象可以为null,否则为空。
@Qualifier(value = "jemi")
private Cat cat;
7、@Resource:引用类型的赋值,默认通过byName的方式实现,
如果找不到名字,则通过byType实现!
如果找不到名字,则通过byType实现!
例:
@Resource(name="kaixin")
private Dog dog;
@Resource(name="kaixin")
private Dog dog;
8、@Nullable:字段可以为null。
IOC能实现业务对象之间的解耦合
例:service和dao对象之间的解耦合
例:service和dao对象之间的解耦合
AOP(Aspect Oriented Program)(面向切面编程)
(OOP面向对象编程的升级)
(OOP面向对象编程的升级)
底层是动态代理
1、JDK代理
使用jdk反射包中的类实现创建代理对象的功能
实现接口的动态代理。
InvocationHandler接口———调用处理程序
Method
Proxy类——————————代理
InvocationHandler接口———调用处理程序
Method
Proxy类——————————代理
2、CGLIB(Code generation Library)代理
使用第三方的工具库,实现代理对象的创建
继承类的动态代理。
应对有些类没有实现接口,采用继承,所以方法不能是final
MethodInterceptor方法拦截器接口、Enhancer增强器
MethodInterceptor方法拦截器接口、Enhancer增强器
扩展
静态代理
角色分析
抽象角色:一般会使用接口或者抽象类来解决。
真实角色:被代理的角色
代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作。
客户:访问代理对象的人
代码步骤
接口——>真实角色——>代理角色——>客户端访问代理角色
代理模式的好处
可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
公共业务就交给代理角色!实现了业务的分工!
公共业务发生扩展的时候,方便集中管理!
公共业务就交给代理角色!实现了业务的分工!
公共业务发生扩展的时候,方便集中管理!
缺点
一个真实角色就会产生一个代理角色,代码量会翻倍~开发效率会变低。
aop:看做是动态代理的规范化,把实现动态代理的步骤进行了一个规范,定义
aop作用
1)在目标类源代码不改变的情况下,增加功能。
2)减少代码的重复
3)专注业务逻辑代码
4)解耦合,给你的业务功能和日志,事务等非业务功能分离
在Spring中的作用:提供声明式事务,允许用户自定义切面。
什么时候考虑使用aop技术
1、给一个系统中存在的类修改功能,但是原有类的功能不完善
但你还没有源代码,使用aop就增加功能。
但你还没有源代码,使用aop就增加功能。
2、给项目中的多个类增加一个相同的功能,使用aop
@Override
public void doSome() {
// System.out.println("方法的执行时间"+new Date());
ServiceTools.doLog();
System.out.println("执行业务方法doSome");
//方法最后,提交事务
// System.out.println("方法执行完毕后,提交事务");
ServiceTools.doTrans();
}
@Override
public void doOther() {
// System.out.println("方法的执行时间"+new Date());
ServiceTools.doLog();
System.out.println("执行业务方法doOther");
// System.out.println("方法执行完毕后,提交事务");
ServiceTools.doTrans();
}
public void doSome() {
// System.out.println("方法的执行时间"+new Date());
ServiceTools.doLog();
System.out.println("执行业务方法doSome");
//方法最后,提交事务
// System.out.println("方法执行完毕后,提交事务");
ServiceTools.doTrans();
}
@Override
public void doOther() {
// System.out.println("方法的执行时间"+new Date());
ServiceTools.doLog();
System.out.println("执行业务方法doOther");
// System.out.println("方法执行完毕后,提交事务");
ServiceTools.doTrans();
}
3、给业务增加方法,日志输出
aop中概念
1、aspect:切面,横切关注点被模块化的特殊对象。即它是一个类。
表示增强的功能,就是一堆代码,完成某个功能,非业务功能,常见的切面
功能有日志,事务,统计信息,参数检查,权限验证
表示增强的功能,就是一堆代码,完成某个功能,非业务功能,常见的切面
功能有日志,事务,统计信息,参数检查,权限验证
2、advice:通知,切面必须要完成的工作。即它是类中的一个方法。
通知表示切面功能执行的时间。
通知表示切面功能执行的时间。
3、pointcut:切入点,切面通知执行的位置。
指多个连接点方法的集合。(多个方法)
指多个连接点方法的集合。(多个方法)
其它术语
target:目标,被通知对象。
给哪个类的方法增加功能,这个类就是目标对象。
给哪个类的方法增加功能,这个类就是目标对象。
Proxy:代理,向目标对象应用通知之后创建的对象。
joinpoint:连接点,与切入点匹配的执行点。
连接业务方法和切面的位置,即类中的业务方法。(一个方法)
连接业务方法和切面的位置,即类中的业务方法。(一个方法)
aop的实现
1、spring:spring在内部实现了aop规范,能做aop的工作。
2、aspectJ:开源的专门做aop的框架。(强大)
1、使用注解就可以实现aop功能
@Aspect:是aspectj框架中的注解。
作用:表示当前类是切面类。
切面类:是用来给业务方法增加功能的类,在这个类中有切面的功能代码
2、使用xml配置文件中的标签实现aop功能
aspectJ框架的使用
1、表示切面的执行时间(规范中叫做Advice(通知;增强)),使用的通知注解
1)@Before:前置通知
在目标方法之前先执行切面的功能
在目标方法之前先执行切面的功能
例:
@Before("execution(public int ..CaculatorImpl.*(int,int))")
@Before("execution(public int ..CaculatorImpl.*(int,int))")
2)@AfterReturning:后置通知
属性
1、value切入点表达式
2、returning自定义的变量,表示目标方法的返回值的。
特点
1、能够获取到目标方法的返回值,可以根据这个返回值做不同的处理功能
2、可以修改此返回值
例:
@AfterReturning(value = "execution(* *..SomeServiceImpl.doOther(..))", returning = "res")
@AfterReturning(value = "execution(* *..SomeServiceImpl.doOther(..))", returning = "res")
3)@Around:环绕通知
环绕通知等同于jdk动态代理,InvocationHandler接口
环绕通知等同于jdk动态代理,InvocationHandler接口
属性
ProceedingJoinPoint等同于Method
特点
1、功能最强的通知,在目标方法的前后都能增强功能
2、控制目标方法是否被调用执行(控制目标方法的访问)
3、修改返回值(能修改原来的目标方法的执行结果,影响最后的调用结果)
应用
经常做事务,在目标方法前开启事务,执行目标方法,在目标方法后提交事务
4)AfterThrowing:异常通知
属性
1、value切入点表达式
2、throwing 自定义变量,表目标方法抛出的异常对象。
变量名必须和方法的参数名一致
变量名必须和方法的参数名一致
特点
1、在目标方法抛出异常时执行的
2、可以做异常的监控程序,监控目标方法执行时是否有异常
如果有异常,可以发送邮件,短信进行通知
如果有异常,可以发送邮件,短信进行通知
5)@After:最终通知,总会被执行的代码
6)@PointCut:定义和管理切入点的辅助注解
1、定义切入点:
@Pointcut("execution(* *..SomeServiceImpl.doSecond(..))")
public void myPt() {
//无需代码
}
@Pointcut("execution(* *..SomeServiceImpl.doSecond(..))")
public void myPt() {
//无需代码
}
2、调用切入点:
@Before(value = "myPt()")
public void myBefore() {
System.out.println("前置通知,在目标方法之前先执行");
}
@Before(value = "myPt()")
public void myBefore() {
System.out.println("前置通知,在目标方法之前先执行");
}
7)代理的使用方式
1、如果目标类有接口,框架使用jdk动态代理
2、如果目标类没有接口,默认使用的cglib动态代理
3、有接口也可以强制使用cglib动态代理
2、表示切面执行的位置,使用的是切入点表达式
*:0至多个参数
..: 用在方法参数中,表示任意多个参数
用在包名后,表示当前包及其子包路径
..: 用在方法参数中,表示任意多个参数
用在包名后,表示当前包及其子包路径
切入点表达式:execution(访问修饰符 返回值 包名.类名.方法名(方法参数)异常)
Spring整合MyBatis
整合的想法:使用spring的IOC技术,
把mybatis框架中使用的对象交给spring统一创建和管理。
spring是容器,存放service、dao、工具类等对象
把mybatis框架中使用的对象交给spring统一创建和管理。
spring是容器,存放service、dao、工具类等对象
mybatis.xml
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<typeAliases>
<typeAlias type="com.kx.entity.Student" alias="student"/>
</typeAliases>
<mappers>
<!-- <mapper resource="com/kx/dao/StudentDao.xml"/>-->
<package name="com.kx.dao.StudentDao"/>
</mappers>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<typeAliases>
<typeAlias type="com.kx.entity.Student" alias="student"/>
</typeAliases>
<mappers>
<!-- <mapper resource="com/kx/dao/StudentDao.xml"/>-->
<package name="com.kx.dao.StudentDao"/>
</mappers>
交给spring的mybatis对象
1、数据源DataSource,使用阿里的Druid连接池
<!--
把数据库的配置信息写在一个独立的文件中,编译修改数据库的配置内容
spring知道jdbc.properties文件的位置
-->
<context:property-placeholder location="classpath:jdbc.properties"/>
把数据库的配置信息写在一个独立的文件中,编译修改数据库的配置内容
spring知道jdbc.properties文件的位置
-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--声明数据源DataSource,作用是连接数据库的-->
<bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!--set注入给DruidDataSource提供连接数据库信息-->
<property name="url"
value="${jdbc.url}"/> <!--setUrl-->
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="${jdbc.max}"/>
</bean>
<bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!--set注入给DruidDataSource提供连接数据库信息-->
<property name="url"
value="${jdbc.url}"/> <!--setUrl-->
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="${jdbc.max}"/>
</bean>
2、SqlSessionFactory对象,使用SqlSessionFactoryBean在内部创建SqlSessionFactory
<!--声明的是mybatis中提供的SqlSessionFactoryBean类,这个类内部创建SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--set注入,把数据库连接池赋给了dataSource属性
configLocation属性是Resource类型,读取配置文件
它的赋值,使用value,指定文件路径,使用classpath:表示文件的路径
-->
<property name="dataSource" ref="myDataSource"/>
<!--mybatis主配置文件的位置-->
<property name="configLocation" value="classpath:mybatis.xml"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--set注入,把数据库连接池赋给了dataSource属性
configLocation属性是Resource类型,读取配置文件
它的赋值,使用value,指定文件路径,使用classpath:表示文件的路径
-->
<property name="dataSource" ref="myDataSource"/>
<!--mybatis主配置文件的位置-->
<property name="configLocation" value="classpath:mybatis.xml"/>
</bean>
3、Dao代理对象,使用MapperScannnerConfigure,
在此类内部调用getMapper(),创建接口的Dao对象
在此类内部调用getMapper(),创建接口的Dao对象
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指定SqlSessionFactory对象的id-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--指定包名,包名是dao接口所在的包名
MapperScannerConfigurer会扫描此包中所有接口,
把每个接口都执行一次getMapper()方法,得到每个接口的dao对象。
创建好的dao对象放到spring的容器中的.dao对象的默认名称是 接口名首字母小写
-->
<property name="basePackage" value="com.kx.dao"/>
</bean>
<!--指定SqlSessionFactory对象的id-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--指定包名,包名是dao接口所在的包名
MapperScannerConfigurer会扫描此包中所有接口,
把每个接口都执行一次getMapper()方法,得到每个接口的dao对象。
创建好的dao对象放到spring的容器中的.dao对象的默认名称是 接口名首字母小写
-->
<property name="basePackage" value="com.kx.dao"/>
</bean>
4、Service对象
<!--声明service-->
<bean id="studentService" class="com.kx.service.impl.StudentServiceImpl">
<property name="studentDao" ref="studentDao"/>
</bean>
<bean id="studentService" class="com.kx.service.impl.StudentServiceImpl">
<property name="studentDao" ref="studentDao"/>
</bean>
Spring对JDBC的支持(spring-jdbc)
1、JdbcTemplate类被设计成为线程安全的,由它来更新查询数据库。(推荐)
2、JdbcDaoSupport类(不推荐)简化DAO实现,该类声明了一个jdbcTemplate。
3、具名参数NamedParameterJdbcTemplate,易于维护,可读性高。
<!--配置jdbcTemplate-->
<bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean name="deptDao" class="com.kx.jdbc.DeptDAO">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean name="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dataSource"/>
</bean>
<bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean name="deptDao" class="com.kx.jdbc.DeptDAO">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean name="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dataSource"/>
</bean>
Spring中事务处理(spring-tx)
事务
什么是事务
事务指一组sql语句集合,这些sql语句的执行是一致的,作为一个整体执行。
事务管理来确保数据的完整性和一致性。
Atomicity:事务是个原子操作,由一系列动作完成,事物的原子性确保动作要么都完成,要么都失败。
Consistency:一旦所有事务动作完成,事务就被提交,数据和资源处于一种满足业务规则的一致性状态中。
Isolation:可能有许多事务会同时处理相同的数据,因此每个事务都应与其他事务隔离开来,防止数据损坏。
Durability:一旦事务完成,无论发生什么系统错误,结果不受影响。通常情况下,事物的结果被写到持久化存储器中。
Atomicity:事务是个原子操作,由一系列动作完成,事物的原子性确保动作要么都完成,要么都失败。
Consistency:一旦所有事务动作完成,事务就被提交,数据和资源处于一种满足业务规则的一致性状态中。
Isolation:可能有许多事务会同时处理相同的数据,因此每个事务都应与其他事务隔离开来,防止数据损坏。
Durability:一旦事务完成,无论发生什么系统错误,结果不受影响。通常情况下,事物的结果被写到持久化存储器中。
事务管理
1、编程式事务管理
2、声明式事务管理(提倡)(SpringAop支持声明式事务管理)
声明式事务:把事务相关的资源和内容都提供给spring,
spring就能处理事务提交,回滚了。几乎不用代码。
声明式事务:把事务相关的资源和内容都提供给spring,
spring就能处理事务提交,回滚了。几乎不用代码。
什么时候用到事务
操作涉及多表或多个sql语句的insert、update、delete。
要么都成功要么都失败。
要么都成功要么都失败。
在java代码中事务应该放在service类的业务方法上,
因为业务方法会调用多个dao方法,执行多个sql语句。
因为业务方法会调用多个dao方法,执行多个sql语句。
通常使用JDBC访问数据库,
用mybatis访问数据库怎么处理事务
用mybatis访问数据库怎么处理事务
jdbc访问数据库,处理事务:conn.commit();conn.rollback();
mybatis访问数据库,处理事务:SqlSession.commit();SqlSession.rollback();
hibernate访问数据库,处理事务:Session.commit();Session.rollback();
在3问题中事务的处理方式,有什么不足
1)不同的数据库访问技术,处理事务的对象,方法不同,需要了解不同数据库
访问技术使用事务的原理。
访问技术使用事务的原理。
2)掌握多种数据库中事务的处理逻辑。何时提交或回滚事务。
3)处理事务的多种方法。
总结:多种数据库的访问技术,有不同的事务处理机制,对象,方法。
处理事务,需要怎么做,做什么
spring处理事务的模型,使用的步骤都是固定的。
把事务使用的信息提供给spring即可。
把事务使用的信息提供给spring即可。
并发事务导致:脏读、不可重复读、幻读
事务隔离级别
read_uncommitted:为解决任何并发问题。
read_committed:解决脏读
repeatable_read(MySQL默认):解决脏读、不可重复读、存在幻读
serializable:串行化。不存在并发问题。(安全性高,性能低)
事务的超时时间
表示一个方法最长的执行时间,如果方法执行时超过了
时间,事务就回滚。单位秒,整数值,默认是-1。
时间,事务就回滚。单位秒,整数值,默认是-1。
事务的7个传播行为,表示业务方法调用时
Propagation.REQUIRED(默认)
Propagation.REQUIRES_NEW
Propagation.SUPPORTS
Propagation.MANDATORY
Propagation.NOT_SUPPORTED
Propagation.NEVER
Propagation.NESTED
Propagation.NOT_SUPPORTED
Propagation.NEVER
Propagation.NESTED
方法提交事务,回滚事务的时机
1、当你的业务方法执行成功,没有抛异常,当方法执行完毕,spring在方法
执行后提交事务
执行后提交事务
2、业务方法抛出运行时异常,spring执行回滚,调用事务管理器的rollback
运行时异常的定义:RuntimeException和它的子类都是运行时异常,例如
NullPointException、NumberFormatException
运行时异常的定义:RuntimeException和它的子类都是运行时异常,例如
NullPointException、NumberFormatException
3、业务方法抛出非运行时异常,主要是受查异常和error时,提交事务
受查异常:写代码时,必须处理的异常:IOException、SQLException
受查异常:写代码时,必须处理的异常:IOException、SQLException
spring框架中提供的事务处理方案
1、适合中小项目使用的,注解方案
spring框架自己用aop实现给业务方法增加事务的功能,使用@Transactional注解增加事务。
@Transactional是spring框架自己的注解,放在public方法上方。表示当前方法具有事务。
可以给注解的属性赋值,表示具体的隔离级别,传播行为,异常信息等。
spring框架自己用aop实现给业务方法增加事务的功能,使用@Transactional注解增加事务。
@Transactional是spring框架自己的注解,放在public方法上方。表示当前方法具有事务。
可以给注解的属性赋值,表示具体的隔离级别,传播行为,异常信息等。
使用@Transactional的步骤:
1)需要声明事务管理器对象
<bean id="xx" class="DataSourceTransactionManager">
2)开启事务注解驱动,告诉spring,我要使用注解的方式管理事务。
spring使用aop机制,创建@Transactional所在的类代理对象,给方法加入事务
的功能。
spring给业务方法加入事务:在业务方法执行前,先开启事务,在业务方法之
后提交或回滚事务,使用aop环绕通知
@Around("增加的事务功能的业务方法名称")
Object myAround(){
//开启事务,spring来开启
try{
buy(1001,10);
spring的事务管理.commit();
}catch(Exception e){
spring的事务管理.rollback();
}
}
3)在方法上方加注解
1)需要声明事务管理器对象
<bean id="xx" class="DataSourceTransactionManager">
2)开启事务注解驱动,告诉spring,我要使用注解的方式管理事务。
spring使用aop机制,创建@Transactional所在的类代理对象,给方法加入事务
的功能。
spring给业务方法加入事务:在业务方法执行前,先开启事务,在业务方法之
后提交或回滚事务,使用aop环绕通知
@Around("增加的事务功能的业务方法名称")
Object myAround(){
//开启事务,spring来开启
try{
buy(1001,10);
spring的事务管理.commit();
}catch(Exception e){
spring的事务管理.rollback();
}
}
3)在方法上方加注解
@Transaction
<!--使用spring事务管理器-->
<!--1、声明事务管理器-->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--连接的数据库,指定数据源-->
<property name="dataSource" ref="myDataSource"/>
</bean>
<!--2、开启事务注解驱动,告诉spring使用注解管理事务,创建代理对象
transaction-manager:事务管理器对象的id
-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
<!--1、声明事务管理器-->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--连接的数据库,指定数据源-->
<property name="dataSource" ref="myDataSource"/>
</bean>
<!--2、开启事务注解驱动,告诉spring使用注解管理事务,创建代理对象
transaction-manager:事务管理器对象的id
-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
//自定义的运行时异常
public class NotEnoughException extends RuntimeException{
public NotEnoughException() {
}
public NotEnoughException(String message) {
super(message);
}
}
public class NotEnoughException extends RuntimeException{
public NotEnoughException() {
}
public NotEnoughException(String message) {
super(message);
}
}
@Transactional(
propagation = Propagation.REQUIRED,
isolation = Isolation.DEFAULT,
readOnly = false,
rollbackFor = {
//两个自定义的异常类
NullPointerException.class,
NotEnoughException.class
}
)
propagation = Propagation.REQUIRED,
isolation = Isolation.DEFAULT,
readOnly = false,
rollbackFor = {
//两个自定义的异常类
NullPointerException.class,
NotEnoughException.class
}
)
2、适合大型项目,有很多的类,方法,需要大量的配置事务,使用aspectj框架功能:
在是spring配置文件中声明类,方法需要的事务。
这种方式业务方法和shi'wu'pei'zhi事务配置完全分离。
在是spring配置文件中声明类,方法需要的事务。
这种方式业务方法和shi'wu'pei'zhi事务配置完全分离。
实现步骤:都是在xml配置文件中实现。
1)要使用的是aspectj框架,需要加入spring-aspects依赖
2)声明事务管理器对象
<bean id="xx" class="DataSourceTransactionManager">
3)声明方法需要的事务类型(配置方法的事务属性:隔离级别,传播行为,超时)
4)配置aop:指定哪些类需要创建代理
1)要使用的是aspectj框架,需要加入spring-aspects依赖
2)声明事务管理器对象
<bean id="xx" class="DataSourceTransactionManager">
3)声明方法需要的事务类型(配置方法的事务属性:隔离级别,传播行为,超时)
4)配置aop:指定哪些类需要创建代理
Spring-Web
实现步骤:
1、创建maven,web项目
2、加入依赖
拷贝my07依赖、加jsp,servlet依赖
3、拷贝my07代码和配置文件
4、创建一个jsp发起请求,有参数id,name,email,age
5、创建Servlet,接收请求参数,调用Service,调用dao完成注册
6、创建一个jsp作为显示结果页面
1、创建maven,web项目
2、加入依赖
拷贝my07依赖、加jsp,servlet依赖
3、拷贝my07代码和配置文件
4、创建一个jsp发起请求,有参数id,name,email,age
5、创建Servlet,接收请求参数,调用Service,调用dao完成注册
6、创建一个jsp作为显示结果页面
拓展
1、Spring的IOC理解
IOC指创建对象的控制权的转移,以前创建对象的主动权和时机是由自己把控的,而现在这种权力转移到Spring容器中,
并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。
DI依赖注入,和控制反转是同一个概念的不同角度的描述,即应用程序在运行时依赖IOC容器来动态注入对象需要的外部资源。
最直观的表达:IOC让对象的创建不用去new了,可以由spring自动生产,使用java的反射机制,
根据配置文件在运行时动态的去创建对象以及管理对象,并调用对象的方法的。
并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。
DI依赖注入,和控制反转是同一个概念的不同角度的描述,即应用程序在运行时依赖IOC容器来动态注入对象需要的外部资源。
最直观的表达:IOC让对象的创建不用去new了,可以由spring自动生产,使用java的反射机制,
根据配置文件在运行时动态的去创建对象以及管理对象,并调用对象的方法的。
2、Spring的AOP理解
抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,
同时提高了系统的可维护性。可用于权限认证、日志、事务处理。
AOP代理主要分为静态代理和动态代理。静态代理的代表为AspectJ;
动态代理则以Spring AOP为代表(JDK动态代理和CGLIB动态代理)。
同时提高了系统的可维护性。可用于权限认证、日志、事务处理。
AOP代理主要分为静态代理和动态代理。静态代理的代表为AspectJ;
动态代理则以Spring AOP为代表(JDK动态代理和CGLIB动态代理)。
3、Spring Bean的生命周期
先说Servlet的生命周期:实例化、初始init、接收请求service、销毁destroy
1、实例化Bean
对于ApplicationContext容器,当容器启动结束后,通过获取BeanDefinition对象中的信息,
实例化所有的bean。
对于ApplicationContext容器,当容器启动结束后,通过获取BeanDefinition对象中的信息,
实例化所有的bean。
2、设置对象属性(依赖注入)
实例化后的对象被封装在BeanWrapper对象中,紧接着,Spring根据BeanDefinition中的信息
以及通过BeanWrapper提供的设置属性的接口完成依赖注入。
实例化后的对象被封装在BeanWrapper对象中,紧接着,Spring根据BeanDefinition中的信息
以及通过BeanWrapper提供的设置属性的接口完成依赖注入。
3、处理Aware接口
Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给Bean。
Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给Bean。
4、BeanPostProcessor
如果想对Bean进行一些自定义的处理,那么可以让Bean实现了BeanPostProcessor接口,
那将会调用postProcessBeforeInitialization(Object obj, String s)方法。
如果想对Bean进行一些自定义的处理,那么可以让Bean实现了BeanPostProcessor接口,
那将会调用postProcessBeforeInitialization(Object obj, String s)方法。
5、InitializingBean 与 init-method
如果Bean在Spring配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法。
如果Bean在Spring配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法。
6、如果这个Bean实现了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Objectobj, String s)方法;
由于这个方法是在Bean初始化结束时调用的,所以可以被应用于内存或缓存技术;
由于这个方法是在Bean初始化结束时调用的,所以可以被应用于内存或缓存技术;
7、DisposableBean
当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的destroy()方法;
当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的destroy()方法;
8、destroy-method
如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。
如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。
4、Spring框架中都用到了哪些设计模式
(1)工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;
(2)单例模式:Bean默认为单例模式。
(3)代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
(4)模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
(5)观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,
所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现--ApplicationListener。
所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现--ApplicationListener。
0 条评论
下一页