JdbcTemplate基本使用
概述:
它是spring框架中提供的一个对象,是对原始繁琐的jdbc API对象的简单封装。
spring框架为我们提供了很多的操作模板类。
例如:操作关系数据的jdbcTemplate和HibermateTemplate,操作nosql数据库的RedisTemplate,操作消息队列的JmsTemplate等等
开发步骤
- 导入Spring-jdbc和Spring-tx坐标
- 创建数据库表和实体
- 创建JdbcTemplate对象
- 执行数据库操作
Spring产生JdbcTemplate对象
我们可以将JdbcTemplate的创建权交给Spring,将数据源DataSource的创建权也交给Spring,在Spring容器内部将数据源DataSource注入到JdbaTemplate模板对象中,配置如下:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test_1"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
使用JdbcTemplate对象进行更新、删除、新增操作
- 首先在xml配置文件中配置JdbcTemplate类
- 连接数据源
- 在类中创建 JdbcTemplate 类
更新
@Test
public void testDelete(){
int row = jdbcTemplate.update("delete from person where id=?",103);
System.out.println(row);
}
AOP的简介
什么是AOP
- AOP未Aspect Oriented Programming的缩写,意思未面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术
- AOP 是 OOP 的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生泛型。
- 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率
- AOP的总结: 把【围绕】着目标代码的固定代码【抽取】出来,【封装】成固定的解决方案,哪里需要,套哪里
AOP的作用及其优势
- 作用: 在程序运行期间,在不修改源码的情况下对方法进行功能增强
- 优势: 减少重复代码,提高开发效率,并且便于维护
AOP 的底层实现
-
实际上 AOP 的底层是通过 Spring 提供的动态代理技术的。
-
在运行期间,Spring 通过动态代理技术动态的生成代理对象,代理对象方法执行时进行增强功能的接入,在去调用目标对象的方法,从而完成功能的增强。
-
常用动态代理技术:
- JDK 代理:基于接口的动态代理技术
- cglib代理:基于父类的动态代理技术
JDK 的动态代理
- 当java程序执行,程序自定义的的 类 被加载,而且继承父类Proxy接口
- 类byte[]动态生成并加载完成 代理对象 的创建,
- 该代理对象,继承父类Proxy接口,并生成代理接口,实现该代理接口的方法
- 代理对象重写接口方法,并完成方法调用转发
- 调用目标对象方法执行
- 得到调用的结果
- 所以使用 JDK 代理生成的类时Proxy的子类,且是被代理接口的子类
- jdk的动态代理其实就是class字节码动态生成并被jvm加载,实例化的操作,其所有的方法都会在其中实现并被转发给目标对象
具体步骤:
- 通过实现 InvocationHandler 接口创建自己的调用处理器;
- 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
- 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
- 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
个人理解:
- 在使用Proxy.newProxyInstance(loader, interfaces, handler)方法时
- 底层经过各方法通过反射创建出代理对象,再将代理对象通过jvm生成字节码文件。
- 通过反编译字节码可知,代理对象继承Proxy最终抛出目标对象的父类接口并实现invoke方法
cglib 的动态代理
-
JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。
-
JDK和Cglib都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码,Cglib代理实现更复杂,生成代理类比JDK效率低。
-
JDK调用代理方法,是通过反射机制调用,Cglib是通过FastClass机制直接调用方法,Cglib执行效率更高。
AOP 的相关概念:
-
spring 的 AOP实现底层就是对上面的动态代理的代码进行了封装,封装后我们只需要对需要关注的部分进行代码编写,并通过配置的方式完成指定目标的方法增强。
-
AOP 的常用术语:
- Target(目标对象):代理的目标对象
- Proxy(代理):一个类被 AOP 织入增强后,就产生了一个代理类
- Joinpoint(连接点):指被拦截到的点,在Spring中这些点指的是被拦截的增强方法
- Pointcut(切入点):指对Joinpoint拦截的方法的定义
- Advice(通知/增强):指被拦截到joinpoint之后所要做的事情(通知或增强)
- Aspect(切面):是切入点和通知的结合
- Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而Aspect采用编译器织入和类装载期织入
AOP 开发明确的事项
- 需要编写的内容
- 编写核心业务代码(目标类的目标方法)
- 编写切面类,切面类中有通知(增强功能方法)
- 在配置文件中,配置织入关系,即将哪些通知与哪些连接点进行结合
- AOP 技术实现的内容
- Spring 框架监控切入点方法的执行。一旦监控到切入点方法被执行,就会使用代理机制,动态创建目标对象的代理对象,根据通知类别,在代理对象的对应位置,将通过对应的功能织入,完成完整的代码逻辑运行
- AOP底层使用哪种代理方法
- 在Spring中,框架会根据目标类是否实现了接口来决定采用哪种动态代理的方式
知识要点:
-
aop:面向切面编程
-
aop底层实现:基于JDK的动态代理和基于Cglib的动态代理
-
aop的重点概念:
- Pointcut(切入点):被增强的方法
- Advice(通知/增强):封装增强业务逻辑的方法
- Aspect(切面):切点+通知
- Weaving(织入):将切点与通知结合的过程
-
开发明确事项:
- 切点表达式配置
- 切面类中的增强方法
- 将切点和通知进行织入配置
XML 方式实现AOP
<!-- 配置目标对象-->
<bean id="target" class="com.DemoTestNode.aop.Target"></bean>
<!-- 配置切面对象-->
<bean id="aspect" class="com.DemoTestNode.aop.MyAspect"></bean>
<!-- 配置织入;告诉Spring【哪些方法】需要【哪些增强】-->
<aop:config>
<aop:aspect ref="aspect">
<aop:before method="before" pointcut="execution(public void com.DemoTestNode.aop.Target.save())"></aop:before>
</aop:aspect>
</aop:config>
- <aop:aspect ref=“aspect”>< /aop:aspect > 配置切面bean
- aop:aspect标签中指定的是切面的哪些方法
- 例如:<aop: before method=“指定增强的方法” pointcut=“切面表达式/切面方法”>
切面表达式的写法:
-
表达式语法:
-
execution([修饰符] 返回值类型 包名.类名.方法名(参数))
-
访问修饰符可以省略
-
返回值类型、包名、类名、方法名可以使用星号* 代表任意
-
包名与类名之间一个点"." 代表当前包下的类,两个类。"…"表示当前包及其子包下的类
-
参数列表可以使用两个带点"…"表示任意个数,任意类型的参数列表
-
例如:
execution(public void com.demotestnode.aop.target.method()) execution(void com.demotestnode.aop.target.*(..)) execution(* com.demotestnode.aop.*.*(..)) execution(* com.demotestnode.aop..*.*(..)) execution(* *..*.*(..))
-
XML配置AOP详情
-
通知的类型
-
语法:< aop:通知类型 method=“切面类中方法名” pointcut=“切点表达式” ></ aop:通知类型>
名称: 标签 说明 前置通知: < aop:before > 用于前置通知。指定增强的方法在切入点方法之前执行 后置通知: < aop:after-returning > 用于配置后置通知。指定增强的方法在切入点方法知州执行 环绕通知: < aop:around > 用于配置环绕通知。指定增强的方法在切入点方法之前和之后都执行 异常抛出通知: < aop:throwing > 用于配置异常抛出童子。指定增强的方法在出现异常时执行 最终通知: < aop:after > 用于配置最终通知。无论增强方式执行是否有异常都会执行
-
切点表达式的抽取
- 当多个增强的切点表达式相同时,可以将切点表达式进行抽取,在增强中使用pointcut-ref熟悉代替pointcut属性来引用抽取后的切点表达式
<aop:config>
<aop:aspect ref="aspect">
<aop:pointcut id="myPointcut" expression="execution(* com.DemoTestNode.aop.*.*(..))"/>
<aop:after method="final_funtion" pointcut-ref="myPointcut"></aop:after>
</aop:aspect>
</aop:config>
知识要点
- aop织入的配置:
<aop:config>
<aop:aspect ref="切面类(bean)">
<aop:before method="”通知方法名称" pointcut="切点表达式"></aop:before>
</aop:aspect>
</aop:config>
- 通知的类型:前置通知、后置通知、环绕通知、异常抛出通知、最终通知
- 切点表达式的写法:
execution([修饰符] 返回值类型 包名.类名.方法名(参数))
基于注解的 AOP 开发
- 需要在Spring配置文件中配置【组件扫描】和开启【AOP自动代理】
<context:component-scan base-package="com.DemoTestNode.annon"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy><!-- 开启 AOP 自动代理 -->
- 切入点注解:
名称: | 标签 | 说明 |
---|---|---|
切入点 | @Pointcut | 该注解配置该方法为一个切入点方法。指定增强方法执行 |
注解通知的类型:
- 通知的配置语法:@通知注解(“切点表达式”)
名称: | 标签 | 说明 |
---|---|---|
前置通知: | @Before | 用于前置通知。指定增强的方法在切入点方法之前执行 |
后置通知: | @AfterReturning | 用于配置后置通知。指定增强的方法在切入点方法知州执行 |
环绕通知: | @Around | 用于配置环绕通知。指定增强的方法在切入点方法之前和之后都执行 |
异常抛出通知: | @AfterThrowing | 用于配置异常抛出童子。指定增强的方法在出现异常时执行 |
最终通知: | @After | 用于配置最终通知。无论增强方式执行是否有异常都会执行 |
知识要点:
- 注解aop开发步骤:
- 使用 @Aspect 标注切面类
- 使用 @ 通知注解标注通知方法
- 在配置文件中配置aop自动代理 < aop:aspectj-autoproxy />
- 通知注解类型:
名称: | 标签 | 说明 |
---|---|---|
前置通知: | @Before | 用于前置通知。指定增强的方法在切入点方法之前执行 |
后置通知: | @AfterReturning | 用于配置后置通知。指定增强的方法在切入点方法知州执行 |
环绕通知: | @Around | 用于配置环绕通知。指定增强的方法在切入点方法之前和之后都执行 |
异常抛出通知: | @AfterThrowing | 用于配置异常抛出童子。指定增强的方法在出现异常时执行 |
最终通知: | @After | 用于配置最终通知。无论增强方式执行是否有异常都会执行 |
编程式事务控制相关对象
PlatfromTransactionManager
PlatfromTransactionManager 接口是Spring的事务管理器,它里面提供了我们常用的操作事务的方法
方法 | 说明 |
---|---|
TransactionStatus | 获取事务的状态信息 |
void commit(TransactionStatus status) | 提交事务 |
void rollaback(TransactionStatus status) | 回滚事务 |
注意:
- PlatformTransactionManager 是接口类型,不同的Dao层技术则右不同的实现类,
- 例如:Dao层技术是jdbc或 myBatis时,提供的接口应为 DataSourceTransactionManager
- Dao层技术是 hibernate时,提供的接口应为:HibernateTransactionManager
TransactionDefinition
TransactionDefinition是事务的定义信息对象,里面右如下方法:
方法 | 说明 |
---|---|
int getIsolationLevel() | 获得事务的隔离级别 |
int getPropogationBehavior() | 获得事务的传播级别 |
int getTimeout() | 获得超时时间 |
boolean isReadOnly() | 是否只读 |
事务隔离级别:
设置隔离级别,可以解决事务并发产生的问题,如脏读、不可重复读和虚读
- ISOLATION_DEFAULT
- ISOLATION_READ_UNCOMMITTED
- ISOLATION_READ_COMMITTED
- ISOLATION_REPEATABLE_READ
- ISOLATION_SERIALIZABEL
事务传播行为:
- REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到事务中。(默认值)
- SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方法执行(没有事务)
- MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常
- REQUERS_NEW:新建事务,如果当前在事务中,把当前事务挂起
- NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
- NEVER:以非事务的方式运行,如果当前存在事务,抛出异常
- NESTED:如果当前存在事务,则嵌套事务内执行,如果当前没有事务,则执行REQUIRED类型的操作
- 超时时间:默认值是-1,没有超时限制。如果右,以秒为单位进行设置
- 是否只读:简易查询时设置为只读
TransactionStatus
TransactionStatus 接口提供的是事务具体的运行状态,方法介绍如下:
方法 | 说明 |
---|---|
boolean hasSavepoint() | 是否存储回滚点 |
boolean isCompleted() | 事务是否完成 |
boolean isNewTransaction() | 是否是新事务 |
boolean isRollbackOnly() | 事务是否回滚 |
基于XML的声明式事务控制
什么是声明式事务控制
- spring 的声明式事务顾名思义就是采用声明的方式来处理事务。这里所说的声明,就是指在配置文件中声明,用 spring 配置文件中声明的处理事务来代替代码式的处理事务
声明式事务处理的作用
- 事务管理不侵入开发的组件。具体来说,业务逻辑对象就不会意识到正在事务管理之中,事实上也应该如此,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分,如果想要改变事务管理策划的话,也只需要在定义文件中重新配置即可
- 也不需要事务管理的时候,只要在设定文件上修改一下,即可移除事务管理服务,无需改变代码重新编译,这样维护起来机器方便
注意:
- Spring 声明式事务控制底层就是 AOP
声明式事务控制的实现
声明式事务的控制明确事项:
- 谁是切点?
- 谁是通知?
- 配置切面
切点方法的事务参数的配置
<tx:advice id="txAdvice" transaction-manager="事务管理器的beanID">
<tx:attributes>
<tx:method name="方法名" timeout="-1" isolation="DEFAULT" read-only="false" />
<tx:method name="*代表所有方法"/>
</tx:attributes>
</tx:advice>
其中,< tx:method > 代表切点方法的事务参数的配置,例如:
<tx:method name="方法名" timeout="-1" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
- name:切点方法的名称
- isolation:事务的隔离级别
- propagation:事务的传播行为
- timeout:超时时间
- read-only:是否只读
基于注解的声明式事务控制
注解配置声明式事务控制解析
- 使用@Transactional 在需要进行事务控制的类或是方法上修饰,注解可用的属性同xml配置方式,例如:隔离级别、传播行为等。
- 注解使用在类上,那么该类下的所有方法都使用同一套注解参数配置
- 使用在方法上,不同的房啊可以采用不同的事务参数配置
- xml配置文件中要开启事务的注解驱动 < tx:annotation-driven >
知识要点:
- 平台事务管理器配置(xml方式)
- 事务通知的配置(@Transactional注解配置)
- 事务注解的配置 < tx:annotation-driven >
😍❤️SSM 专栏前篇
- 【SSM-Spring(一)】初上手Spring?别急!从最底部开始学习Spring吧!从Bean开始!本文介绍Spring程序的开发、Bean的声明周期与依赖注入概念
- 【SSM-Spring(二)】初上手Spring?别急!从最底部开始学习Spring吧!Spring连接数据库、注解开发、Junit测试
- 【SSM-SpringMVC(一)】Spring接入Web环境!本篇开始研究SpringMVC的使用!本文介绍了SpringMVC,以及SpringMVC的执行流程和常用注解解析
- 【SSM-SpringMVC(二)】Spring接入Web环境!本篇开始研究SpringMVC的使用!SpringMVC数据响应和获取请求数据