SSM_Spring
Day -01
第一章 简介
1.1. Spring概述
Spring是一个为简化企业级开发而生的开源框架。使用Spring开发可以将 Bean对象,Dao组件对象,Service组件对象等交给Spring容器来管理,这样使得很多复杂的代码在Spring中开发却变得非常的优雅和简洁,有效的降低代码的耦合度,极大的方便项目的后期维护、升级和扩展。
★★★ Spring是一个IOC(DI)和AOP容器框架。
1.2.Spring优良特性:
1) **非侵入式:**基于Spring开发的应用中的对象可以不依赖于Spring的API。
2) 控制反转:IOC——Inversion of Control,指的是将对象的创建权交给Spring去创建。使用Spring之前,对象的创建都是由我们自己在代码中new创建。而使用Spring之后。对象的创建都是由给了Spring框架。
3) **依赖注入:**DI——Dependency Injection,是指依赖的对象不需要手动调用setXXX方法去设置,而是通过配置赋值。
4) **面向切面编程:**AOP——Aspect Oriented Programming,在不修改源代码的基础上进行功能扩展。
5) **容器:**Spring是一个容器,因为它包含并且管理应用对象的生命周期。
6) **组件化:**Spring实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用XML和Java注解组合这些对象。
7)**一站式:**在IOC和AOP的基础上可以整合各种企业应用的开源框架和优秀的第三方类库(实际上Spring 自身也提供了表述层的SpringMVC和持久层的JDBCTemplate)
1.3 Spring模块
Spring框架分为五大模块:
1) Core Container:核心 容器
l Beans提供 BeanFactory,它是一个工厂模式的复杂实现。
l Core提供了框架的基本组成部分,包括IOC和DI功能。
l Context建立在由核心和 Bean 模块提供的基础上,它是访问定义和配置的任何对象的媒介。ApplicationContext 接口是上下文模块的重点。
l SpEL在运行时提供了查询和操作一个对象的强大的Spring表达式语言。
2) AOP&Aspects:提供了面向切面编程的实现。
3) DataAccess/Integration:提供了对数据访问/集成的功能。
4) Web:提供了面向Web应用程序的集成功能。
5) Test:提供了对JUnit 或 TestNG 框架的测试功能。
1.4 IOC和DI
① IOC(Inversion of Control):反转控制
在应用程序中的组件需要获取资源时,传统的方式是组件主动的从容器中获取所需要的资源,在这样的模式下开发人员往往需要知道在具体容器中特定资源的获取方式,增加了学习成本,同时降低了开发效率。
反转控制的思想完全颠覆了应用程序组件获取资源的传统方式:反转了资源的获取方向——改由容器主动的将资源推送给需要的组件,开发人员不需要知道容器是如何创建资源对象的,只需要提供接收资源的方式即可,极大的降低了学习成本,提高了开发的效率。这种行为也称为查找的被动形式。
② DI(Dependency Injection):依赖注入
IOC的另一种表述方式:即组件以一些预先定义好的方式(例如:setter 方法)接受来自于容器的资源注入。相对于IOC而言,这种表述更直接。
总结: IOC 就是一种反转控制的思想, 而DI是对IOC的一种具体实现。
③IOC容器在Spring中的实现
在创建Bean之前,首先需要创建IOC容器。Spring提供了IOC容器的两种实现方式:
1) BeanFactory:IOC容器的基本实现,是Spring内部的使用接口,是面向Spring本身的,不是提供给开发人员使用的。
2) ApplicationContext:BeanFactory的子接口,提供了更多高级特性。面向Spring的使用者,几乎所有场合都使用ApplicationContext而不是底层的BeanFactory。
④ ApplicationContext的主要实现类
☆☆☆☆☆☆1) ClassPathXmlApplicatio nContext:对应类路径下的XML格式的配置文件
2) FileSystemXmlApplicationContext:对应文件系统中的XML格式的配置文件
3) ConfigurableApplicationContext:是ApplicationContext的子接口,包含一些扩展方法refresh()和close(),让ApplicationContext具有启动、关闭和刷新上下文的能力。
4) WebApplicationContext:专门为WEB应用而准备的,它允许从相对于WEB根目录的路径中完成初始化工作。
⑤ 获取bean的方式
★★★★★1) 根据bean的id获取 (常用的)
l 需要强转
HelloWorld helloWorld = (HelloWorld) ioc.getBean("helloWorld");
2) 根据bean的类型获取
l 如果在IOC容器中有多个该类型的bean则会抛出异常
HelloWorld helloWorld = ioc.getBean(HelloWorld.class);
3) 根据bean的id和类型获取
HelloWorld helloWorld = ioc.getBean(“helloWorld”, HelloWorld.class);
第二章 基于XML的方式管理Bean
2.1 创建Bean
让Spring的IOC容器帮我们创建Bean,只需要在Spring的配置文件中通过bean标签配置即可。
bean标签中常用属性说明:
1) Id属性:给IOC容器中的bean设置的唯一标识。
2)class属性:配置让IOC容器管理的类的全类名,Spring会利用反射技术通过类的《无参构造器》创建对象。
-<bean class="com.atguigu.spring.helloworld.HelloWorld" id="helloWorld">
2.2 给Bean的属性赋值
① ★★★★★ setter注入
在bean标签中通过 property 标签设置bean的属性值,property标签中的属性
l name属性:配置bean的属性名
l value属性:配置bean的属性值
l 还可以通过value子标签配置bean的属性值
<bean class="com.atguigu.spring.beans.Book" id="book1" >
<property name="id" value="1"></property>
<property name="title" value="三国演义"></property>
<property name="author" value="罗贯中"></property>
<property name="price" value="66.66"></property>
<property name="sales" value="100"></property>
</bean>
② 构造器注入
在bean标签中通过constructor-arg标签设置bean的属性值,constructor-arg标签中的属性说明:
l name属性:配置构造器中的参数名
l value属性:配置参数值
l index属性:配置参数在构造器中的索引位置,从0开始
l type属性:配置构造器中参数的类型
1) 只指定value属性,自动匹配合适的构造器
<bean id="book2" class="com.atguigu.spring.beans.Book">
<constructor-arg value="2"></constructor-arg>
<constructor-arg value="水浒传"></constructor-arg>
<constructor-arg value="施耐庵"></constructor-arg>
<constructor-arg value="88.88"></constructor-arg>
<constructor-arg value="100"></constructor-arg>
</bean>
2)1) 所有属性都指定
<bean id="book3" class="com.atguigu.spring.beans.Book">
<constructor-arg name="id" value="3"></constructor-arg>
<constructor-arg name="title" value="红楼梦"></constructor-arg>
<constructor-arg index="2" value="曹雪芹"></constructor-arg>
<constructor-arg type="java.lang.Integer" value="100"></constructor-arg>
</bean>
③ 特殊值处理
1) 字面量
字面量是用于表达源代码中一个固定值的表示法。基本数据类型及其包装类型、String等类型都可以采取字面值注入的方式。
2) 赋null值
通过标签给bean的属性赋null值
3) 赋值中包含特殊字符
若字面值中包含特殊字符,可以使用<![CDATA[ ]]>把字面值包裹起来
<bean id="book4" class="com.atguigu.spring.beans.Book">
<property name="id" value="4"></property>
<property name="title">
<value><![CDATA[<<西游记>>]]></value>
</property>
<property name="author" value="吴承恩"></property>
<property name="sales">
<null></null>
</property>
</bean>
④ 2.2.4 使用p名称空间
使用p名称空间需要引入对应的约束,在Idea中根据提示引入即可。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--通过p名称空间配置bean-->
<bean id="book5" class="com.atguigu.spring.beans.Book"
p:id="5" p:title="解忧杂货店"
p:author="藤野圭吾"
p:price="33.00"
p:sales="100"></bean>
</beans>
⑤ ★★★ 引用外部已声明的bean
当bean的属性是一个其他类型的对象是,可以在property或标签中通过ref属性或ref子标签引用IOC容器中配置好的该类型的bean,ref的属性值指定为引用的bean的id值。
<bean id="cartItem" class="com.atguigu.spring.beans.CartItem">
<!--引用外部bean-->
<property name="book" ref="book1"></property>
<property name="count" value="10"></property>
<property name="amount" value="100"></property>
</bean>
⑥内部bean
当bean实例仅仅给一个特定的属性使用时,可以将其声明为内部bean。内部bean声明直接包含在或元素里,不需要设置id。
<bean id="cartItem2" class="com.atguigu.spring.beans.CartItem">
<property name="book">
<!--配置内部bean-->
<bean class="com.atguigu.spring.beans.Book">
<property name="id" value="6"></property>
<property name="title" value="三体"></property>
<property name="author" value="刘慈欣"></property>
<property name="price" value="22.00"></property>
<property name="sales" value="100"></property>
</bean>
</property>
<property name="count" value="10"></property>
<property name="amount" value="100"></property>
</bean>
<bean id**=“book3”** class**=“com.atguigu.spring.beans.Book”> <constructor-arg name**=“id” value**=“3”></constructor-arg> <constructor-arg name**=“title” value**=“红楼梦”></constructor-arg> <constructor-arg index**=“2” value**=“曹雪芹”></constructor-arg> <constructor-arg type**=“java.lang.Integer” value**=“100”**></constructor-arg> </bean>
⑦ ★★★级联属性赋值
当bean的属性是一个对象,我们可以通过配置当前bean的方式给属性中对象的属性赋值,即给属性的属性赋值,这种方式我们称为给级联属性赋值。
<!--给级联属性赋值-->
<bean id="cartItem3" class="com.atguigu.spring.beans.CartItem">
<property name="book" ref="book1"></property>
<!--通过给级联属性赋值将book1中的title修改为新三国-->
<property name="book.title" value="新三国"></property>
</bean>
⑧ 自动装配
手动装配:以value或ref的方式明确指定属性值都是手动装配。
自动装配:根据bean标签的autowire属性指定的装配规则,不需要明确指定,Spring自动将匹配的属性值注入bean中。
自动装配的规则,即autowire的属性值有:
l no或default:不自动装配
l byName:根据bean的属性名称自动装配,以当前bean的属性名作为id从IOC容器中寻找以实现装配。找到则装配,找不到则不装配。
l byType:根据bean的属性类型自动装配。找到一个则装配,找到多个则报错,找不到则不装配。
l constructor:根据bean的属性的构造器自动装配,不推荐使用。
⑨★★★★★引入外部属性文件
德鲁伊
当bean的配置信息逐渐增多时,查找和修改一些bean的配置信息就变得愈加困难。这时可以将一部分信息提取到bean配置文件的外部,以properties格式的属性文件保存起来,同时在bean的配置文件中引用properties属性文件中的内容,从而实现一部分属性值在发生变化时仅修改properties属性文件即可。这种技术多用于连接数据库的基本信息的配置。
-
导入druid-1.1.9.jar和mysql-connector-java-5.1.37-bin.jar
-
在src目录下创建外部属性文件druid.properties
#key=value
jdbc.username=root
jdbc.password=root
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.initialSize=5
jdbc.maxActive=10
- 在Spring的配置文件中通过<context:property-placeholder location=”classpath:druid.properties”/>标签引入外部属性文件”
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
https://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--引入外部属性文件-->
<context:property-placeholder location="classpath:druid.properties"></context:property-placeholder>
<!--配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
<property name="initialSize" value="${jdbc.initialSize}"></property>
<property name="maxActive" value="${jdbc.maxActive}"></property>
</bean>
⑩ FactoryBean
Spring中有两种类型的bean,一种是普通bean,另一种是工厂bean,即FactoryBean。普通bean设置的类型就是返回的类型;工厂bean设置的类型可以和返回的类型不一样,其返回的类型通过该工厂bean的getObject方法指定。
创建工厂bean必须实现org.springframework.beans.factory.FactoryBean接口。
创建工厂bean的步骤:
- 创建一个类实现FactoryBean接口
package com.atguigu.spring.beans;
import org.springframework.beans.factory.FactoryBean;
public class MyFactoryBean implements FactoryBean<Book> {
//设置返回的对象
@Override
public Book getObject() throws Exception {
return new Book(7,"生命不息,奋斗不止","罗永浩",11.11,1000);
}
//设置对象的类型
@Override
public Class<?> getObjectType() {
return Book.class;
}
//设置当前bean是否是单例的
@Override
public boolean isSingleton() {
return true;
}
}
- 在Spring的配置文件中配置工厂bean
<!--配置工厂bean-->
<bean id="myFactoryBean" class="com.atguigu.spring.beans.MyFactoryBean"></bean>
3)测试
/*
测试工厂bean
*/
@Test
public void testFactoryBean(){
Book book = (Book) ioc.getBean("myFactoryBean");
System.out.println(book);
2.3 Bean的作用域
在Spring中,可以在bean标签的scope属性里设置bean的作用域,
Bean的作用域通过bean标签的scope属性设置bean的作用域 scope的值的说明: singleton:默认值。IOC容器一创建就实例化该对象,而且是单例的,每次调用getBean方法得到的都是同一个
prototype:原型的。IOC容器一创建将不再实例化对象,每次调用getBean方法时才实例化对象,而且每调用一次getBean方法创建一个新的对象
request:每次发送请求创建一个新的实例 session:每次会话创建一个实例,同一个会话中共享同一个实例
类别 | 说明 |
---|---|
singleton | 在Spring的IOC容器中仅存在一个Bean实例 |
prototype | 每次调用getBean方法都返回一个新的Bean实例 |
request | 每次HTTP请求都会创建一个新的Bean实例,该作用域仅适用于WebApplicationContext环境 |
session | 同一个Session会话共享一个Bean实例,该作用域仅适用于WebApplicationContext环境 |
-
```xml
```
2.4 Bean的生命周期
- Spring IOC容器对bean的生命周期进行管理的过程:
使用注解标识组件
第一步
在让Spring创建对象的类上添加对应的注解:
1) @Component(普通组件)
标识一个受Spring IOC容器 管理的 普通组件
- @Repository( 数据访问层)Dao的实现类上
标识一个受Spring IOC容器管理的持久化层组件
- @Service(业务逻辑层)
标识一个受Spring IOC容器管理的 业务逻辑层 组件`
- @Controller (表现层 servlet)
标识一个受Spring IOC容器管理的 表述层控制器 组件
第二步
在Spring的配置文件中配置自动扫描的包 -
配置自动扫描的包 base-package属性:指定一个基础包,Spring会自动扫描该包及其子包
<context:component-scan base-package="com.atguigu.spring.annotation"/>
① 自动扫描的包 base-package属性:指定一个基础包,Spring会自动扫描该包及其子包
② ★★★ l 设置指定扫描的包
子标签context:include-filter;是用来设置扫描那个包下的类
如果 type是 annotation 那么expression的值是注解的全类名
如果type 是 assignable 那么 expression的值是接口或者实现类的全类型名
注意 :需要将父类的标签 use-default-filters=“false”> 设置为 false 否则 include无效
<context:component-scan base-package="com.atguigu.spring.annotation"use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
③★★★ l 设置不扫描指定的包
子标签context:exclude-filter;是用来设置不扫描那个包下的类
如果 type是 annotation 那么expression的值是注解的全类名
如果type 是 assignable 那么 expression的值是接口或者实现类的全类型名
注意;不能排除Component注解 因为其他三个注解都添加了该注解
<context:component-scan base-package="com.atguigu.spring.annotation">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
3.2 ★★★ 给Bean的属性注入值——自动装配
基于注解的方式实现自动装配(依赖注入)的规则:
1.根据属性的类型实现自动装配。
2.如果根据类型无法实现自动装配,则以属性名作为Id 从IOC容器中寻找实现自动装配
3 如果通过1和2都无法实现自动装配,我们可以通过@Qualifier 注解的value 属性值指定id
实现自动装配,value属性名可以省略不写。
3.3 ★★★★★★完全注解开发
- @Configuration
添加了该注解的类将是一个配置类,用来代替xml配置文件
- @ComponentScan
配置要扫描的包
第四章 AOP
4.1Aop概述
为什要学代理模式?
★★★因为这就是SpringAOP的底层实现 【springAOP和springMVC】面试必问
代理模式分类:
①静态代理
②动态代理
代理模式好处:可以是真实角色操作更加纯粹,用去关注一些公共业务
公共业务可以交给代理角色,实现业务分工
公共业务发生扩展时候,方便集中管理
缺点:一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率变低
4.2 动态代理
1) 动态代理的原理
代理设计模式的原理:使用一个代理将原本对象包装起来,然后用该代理对象”取代”原始对象。任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。
2) 动态代理的方式
a) 基于接口实现动态代理: JDK动态代理 {在这里使用这个}
b) 基于类: Cglib
c)java字节码实现:Javassist
3) 需要了解2个类;
proxy:代理
invocationHandler:(接口,反射包下的)调用处理程序
4)动态代理的好处:
可以是真实角色操作更加纯粹,用去关注一些公共业务
公共业务可以交给代理角色,实现业务分工
公共业务发生扩展时候,方便集中管理
一个动态代理类代理的是一个一个接口,一般就是对应的一类业务、
4.3 Aop在Spring 中的作用
提供声明事务:允许用户自定义切面
① 横切面关注点:跨越应用程序多个模块的方法和功能。即是 与我们业务无关,但是我们需要关注的部分,就是横切关注点,如日志,安全,缓存,事务等等…
② 切面(aspect) :横切关注点 被模块化的特殊对象。即,它是一个类
③ 通知(Advice) : 切面必须要完成的工作。 即, 它是一个类中的方法
⑥ 切入点(pointcut)切面通知执行的” 地点“ 的定义
⑦连接点 (Jointpoint) 与切入匹配的执行点
④目标(Target) : 被通知对象
⑤代理(proxy) : 相目标对象应用通知之后创建的对象
4.4 使用Spring实现AOP
方式一:使用Sprng的Api 接口实现
方式二 :自定义来实现 aop
★★★★★方式三:基于注解的方式实现
@Aspect注解
在Spring中声明切面使用@Aspect注解,而且切面也需要交给IOC容器管理,即切面上也需要添加@Component注解。
当在Spring IOC容器中初始化AspectJ切面之后,Spring IOC容器就会为那些与 AspectJ切面相匹配的bean创建代理。
在AspectJ注解中,切面只是一个带有@Aspect注解的Java类,它往往要包含很多通知,通知是标注有某种注解的简单的Java方法。
AspectJ支持5种类型的通知注解:
① @Around:环绕通知,围绕着方法执行,相当于动态代理的全过程
② @Before:前置通知,在方法执行之前执行
③ @After:后置通知,在方法执行之后执行,不管方法是否发生异常
④ @AfterReturning:返
回通知,在方法返回结果之后执行
⑤ @AfterThrowing:异常通知,在方法抛出异常之后执行
★★★★★ 环绕通知
<!-- 配置自动扫描包-->
<context:component-scan base-package="com.atguigu.aop"></context:component-scan>
<!-- 开启Aspect注解支持-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
创建一个类作为切面,并在切面中添加通知的方法
JoinPoint (连接点)
ProceedingJoinPoint ( 加工接合点)
通过@Around注解标识
环绕通知是所有通知类型中功能最为强大的,能够全面地控制连接点,甚至可以控制是否执行连接点。
对于环绕通知来说,连接点的参数类型必须是ProceedingJoinPoint。它是 JoinPoint的子接口,允许控制何时执行,是否执行连接点。
在环绕通知中需要明确调用ProceedingJoinPoint的proceed()方法来执行被代理的方法。如果忘记这样做就会导致通知被执行了,但目标方法没有被执行。
注意:环绕通知的方法需要返回目标方法执行之后的结果,即调用 joinPoint.proceed()的返回值,否则会出现异常
//环绕通知,相当于动态代理的全过程。
@Order//设置切面优先级
@Component//将切面交给Spring来管理
@Aspect//声明当前类是一个切面
public class LoggingAspect {
@Around("execution(* Calculator.*(..))")
public Object aroundAdivce(ProceedingJoinPoint proceedingJoinPoint) {
//获取方法名
String methodName = proceedingJoinPoint.getSignature().getName();
//获取调用方法时传入的参数
Object[] args = proceedingJoinPoint.getArgs();
Object result=null;
try {
//前置通知
System.out.println("☆☆☆☆☆LoggingThe method " + methodName + " begins with " + Arrays.toString(args));
result = proceedingJoinPoint.proceed();
//返回通知
System.out.println("☆☆☆☆☆Logging: The method "+methodName+" returns "+result);
} catch (Throwable throwable) {
throwable.printStackTrace();
//异常通知
System.out.println("☆☆☆☆☆Logging: The method "+methodName+" occurs "+throwable);
}finally {
//后置通知
System.out.println("☆☆☆☆☆Logging: The method "+methodName+" ends");
}
return result;
}
}
★★★★★ 切入点表达式的表示方式
1.execution(public int com.atguigu.spring.aop.Calculator.add(int,int))
当执行com.atguigu.spring.aop包下的Calculator接口中的add方法时执行通知方法,方法的参数类型的个数 是两个,并且参数的类型都是int;权限修饰符是public,方法的返回值是int
2.execution(public int Calculator.add(int,int))
当执行与切面在同一个包下的Calculator接口中的add方法时执行通知方法,方法的参数类型
的个数是两个,并且参数的类型都是int;权限修饰符是public,方法的返回值是int
3.execution(public int Calculator.*(int,int))
当执行与切面在同一个包下的Calculator接口中的所有方法时执行通知方法,方法的参数类型
的个数是两个,并且参数的类型都是int;权限修饰符是public,方法的返回值是int
4.execution(* Calculator.*(int,int))
当执行与切面在同一个包下的Calculator接口中的所有方法时执行通知方法,方法的参数类型
的个数是两个,并且参数的类型都是int;不考虑权限修饰符和方法的返回值的类型
5.execution(* Calculator.*(..))
当执行与切面在同一个包下的Calculator接口中的所有方法时执行通知方法,不考虑参数的
类型和个数,也不考虑权限修饰符和方法的返回值的类型
6.execution(* *.*(..))
当执行所有接口的所有方法时执行通知方法,不考虑参数的
类型和个数,也不考虑权限修饰符和方法的返回值的类型
7.还可以使用||、&&、!
例如:
execution(* Calculator.add(..)) || execution(* Calculator.sub(..))
当执行与切面在同一个包下的Calculator接口中的add或sub方法时执行通知方法,不考虑参数的
类型和个数,也不考虑权限修饰符和方法的返回值的类型
4.5 JdbcTemplate
第一步 环境搭建
① 导入jar包
1)Spring的核心包
spring-beans-5.3.1.jar
spring-context-5.3.1.jar
spring-core-5.3.1.jar
spring-expression-5.3.1.jar
spring-jcl-5.3.1.jar
spring-aop-5.3.1.jar
2)JdbcTemplate需要的jar包
spring-jdbc-5.3.1.jar
spring-orm-5.3.1.jar
spring-tx-5.3.1.jar
3)连接数据库的驱动jar包和数据源
mysql-connector-java-5.1.37-bin.jar
druid-1.1.9.jar
4)单元测试的jar包
junit-4.12.jar
hamcrest-core-1.3.jar
② 创建数据库和表
在MySQL中执行资料中的jdbc_template.sql文件生成对应的数据库和表。
③ 创建druid.properties文件
#key=value
jdbc.username=root
jdbc.password=root
jdbc.url=jdbc:mysql://localhost:3306/jdbc_template
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.initialSize=5
jdbc.maxActive=10
④ 创建Spring的配置文件
<!--引入外部属性文件-->
<context:property-placeholder location="classpath:druid.properties"></context:property-placeholder>
<!--配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
<property name="initialSize" value="${jdbc.initialSize}"></property>
<property name="maxActive" value="${jdbc.maxActive}"></property>
</bean>
<!--配置JdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--配置数据源属性-->
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
第二步 操作数据库
① 测试JdbcTemplate中通用的增删改的方法
@Test
public void testUpdate() {
//写sql语句
String sql = "delete from employee where id = ?";
//调用JdbcTemplate中的update方法
int update = jdbcTemplate.update(sql, 8);
System.out.println(update > 0 ? "删除成功!" : "删除失败!");
}
② 测试JdbcTemplate中批处理的方法
public void testBatchUpdate() {
//写sql语句
String sql = "insert into employee(last_name,email,salary) values(?,?,?)";
/*
调用的是JdbcTemplate中的batchUpdate方法,该方法中需要传入一个List<Object[]>,
List的size就是sql语句执行的次数,Object[]中的值就是执行每条sql语句时要填充的占位符
*/
List<Object[]> params = new ArrayList<>();
params.add(new Object[]{"董明珠", "dongmignqu@geli.com", 9999.99});
params.add(new Object[]{"王健林", "wangjianlin@wanda.com", 8888.88});
params.add(new Object[]{"王石", "wangshi@wanke.com", 6666.66});
jdbcTemplate.batchUpdate(sql, params);
}
③ 测试JdbcTemplate中查询单一值的方法
调用的是JdbcTemplate中的queryForObject方法
public void testGetSingleValue() {
//写sql语句
String sql = "select salary from employee where id = ?";
//调用JdbcTmplate中的queryForObject方法
Double salary = jdbcTemplate.queryForObject(sql, Double.class,7);
System.out.println(salary);
}
④ 测试JdbcTemplate中查询一个对象的方法
调用的是JdbcTemplate中的 queryForObject 方法
public void testGetOne(){
//写sql语句
String sql = "select id,last_name,email,salary from employee where id = ?";
/* 调用JdbcTemplate中的queryForObject方法
里面需要传入一个行的映射器RowMapper,使用的实现类是BeanPropertyRowMapper,
相当于QueryRunnner中的BeanHandler
注意:当调用queryForObjec方法查询一个对象的时候
如果查不到数据则抛出异常: EmptyResultDataAccessException、
如果查到多条数据也会抛出异常:IncorrectResultSizeDataAccessException
只有查询得到一个记录才能正常处理 */
//创建RowMapper对象
RowMapper<Employee> rowMapper = new BeanPropertyRowMapper<>(Employee.class);
//调用JdbcTemplate中的queryForObject方法
Employee employee = jdbcTemplate.queryForObject(sql, rowMapper,1);
System.out.println(employee);
}
⑤测试JdbcTemplate中获取所有对象的方法
/*
调用的是JdbcTemplate中的 query 方法
*/
@Test
public void testGetAll() {
//写sql语句
String sql = "select id,last_name,email,salary from employee";
//创建RowMapper对象
RowMapper<Employee> rowMapper = new BeanPropertyRowMapper<>(Employee.class);
//调用JdbcTemplate中的query方法
List<Employee> employees = jdbcTemplate.query(sql, rowMapper);
//遍历
for (Employee employee : employees) {
System.out.println(employee);
}
}
第五章 声明式事务
5.1 基于注解方式的声明式事务
★★★★★①第一步 在Spring的配置文件中添加以下配置
<!--配置事务管理器-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<!--配置数据源属性-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--开始事务注解支持
transaction-manager属性:设置事务管理器,值是事务管理器的id值
如果事务管理器的id值是transactionManager,那么该属性可以省略不指定
-->
<tx:annotation-driven></tx:annotation-driven>
★★★★★②第二步 在需要添加事务的方法上添加@Transactional注解
★★★★★★5.2 事务的传播行为
什么是事务的传播行为: 一个事务方法(开启了事务的方法)运行在了另一个事务方法中时,
当前方法是使用原来的事务,还是将原来的事务挂起,开启一个新的事务
@Transactional(propagation = Propagation.REQUIRES_NEW
@Transactional注解中属性说明:
★1.propagation:用来设置事务的传播行为
属性值说明:
Propagation.REQUIRED:默认值,使用原来的事务
Propagation.REQUIRES_NEW:将原来的事务挂起,开启一个新的事务
★★★★★★★5.3事务的隔离级别
isolation:用来设置事务的隔离级别
@Transactional(propagation = Propagation.REQUIRES_NEW,isolation = Isolation.READ_COMMITTED,
隔离级别一共四种:
Isolation.READ_UNCOMMITTED:读未提交
★★★★ Isolation.READ_COMMITTED:读已提交(Oracle数据库默认)
Isolation.REPEATABLE_READ:可重复读(MySQL数据库默认)
Isolation.SERIALIZABLE:串行化
MySQL数据库四种隔离级别都支持;Oracle数据库只支持读已提交和串行化
通常我们使用的隔离级别就是读已提交
第六章 回顾和总结
① 思想的学习 IOC和 Aop
② 重点用的
@Autowired
- @Configuration
添加了该注解的类将是一个配置类,用来代替xml配置文件
- @ComponentScan
③ 动态代理
核心是反射
@Transactional(propagation = Propagation.REQUIRES_NEW
@Transactional注解中属性说明:
★1.propagation:用来设置事务的传播行为
属性值说明:
Propagation.REQUIRED:默认值,使用原来的事务
Propagation.REQUIRES_NEW:将原来的事务挂起,开启一个新的事务
★★★★★★★5.3事务的隔离级别
isolation:用来设置事务的隔离级别
@Transactional(propagation = Propagation.REQUIRES_NEW,isolation = Isolation.READ_COMMITTED,
隔离级别一共四种:
Isolation.READ_UNCOMMITTED:读未提交
★★★★ Isolation.READ_COMMITTED:读已提交(Oracle数据库默认)
Isolation.REPEATABLE_READ:可重复读(MySQL数据库默认)
Isolation.SERIALIZABLE:串行化
MySQL数据库四种隔离级别都支持;Oracle数据库只支持读已提交和串行化
通常我们使用的隔离级别就是读已提交
第六章 回顾和总结
① 思想的学习 IOC和 Aop
[外链图片转存中…(img-7LTbJ1j3-1624200452610)]
② 重点用的
@Autowired
[外链图片转存中…(img-uBQ9sSFJ-1624200452611)]
- @Configuration
添加了该注解的类将是一个配置类,用来代替xml配置文件
- @ComponentScan
③ 动态代理
核心是反射