文章目录
1.Spring
1.1 简介
- 官网地址:Spring
- Spring是一款以IOC(控制反转)和AOP(面向切面)为核心, 简化企业应用复杂性开发的一款轻量级框架。
- 使用:导入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.3</version>
</dependency>
1.2 优点
- Spring是一个开源的免费框架
- Spring是一个轻量级的,非入侵式框架
- 控制反转和面向切面编程
- 支持事务管理,对框架整合的支持
2. IOC理论推导
2.1.代码实现
- UserDao接口
public interface UserDao {
void food();
}
- UserDaoImpl实现类
public class UserDaoImpl implements UserDao {
public void food() {
System.out.println("苹果");
}
}
- userService业务接口
public interface Userservice {
void food();
}
- UserServiceImpl业务实现
public class UserServiceImpl implements Userservice {
private UserDao userDao=new UserDaoImpl();
public void food() {
userDao.food();
}
}
- 在我们之前的业务中,用户需求可能会影响原来的代码,我们要根据用户的需求取修改原代码,如果程序代码里大,那么修改成本会非常昂贵
- 我们使用一个set接口实现:
public class UserServiceImpl implements Userservice {
private UserDao userDao;
// 使用set实现动态调用
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void food() {
userDao.food();
}
}
- 之前程序是主动创建对象,控制权在程序员
- 使用set注入后,程序不在具有主动性,而是被动的接受对象
- 这种思想从本质解决问题,对象不在由程序控制,系统耦合性大大降低,程序员只需专注于业务逻辑的实现,这就是IOC的原型。
2.2 IOC本质
- 控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。
- 没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
- IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。
总结:所谓的IOC就是对象由spring容器创建,管理,装配
3.Spring第一个程序
3.1 代码
- ApplicationContext.xml:
<?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">
<bean id="UserDaoImpl" class="com.wu.dao.UserDaoImpl">
<property name="username" value="杨幂"/>
</bean>
<bean id="UserServiceImpl" class="com.wu.service.UserServiceImpl">
<!-- ref:引用spring中创建的对象
value:具体的基本数据类型的值-->
<property name="userDao" ref="UserDaoImpl"/>
</bean>
</beans>
- 测试代码
public void Test01(){
//获取ApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("UserServiceImpl");
userServiceImpl.food();
}
3.2 IOC创建对象的方式
- 使用无参构造器创建对象,默认(必须有set方法)
<bean id="UserDaoImpl" class="com.wu.dao.UserDaoImpl">
<property name="username" value="杨幂"/>
</bean>
- 使用有参构造器创建对象
- 构造器参数下标赋值,不建议使用
<bean id="UserDaoImpl" class="com.wu.dao.UserDaoImpl">
<constructor-arg index="0" value="赵丽颖"/>
</bean>
- 构造器参数类型赋值
<bean id="UserDaoImpl" class="com.wu.dao.UserDaoImpl">
<constructor-arg type="java.lang.String" value="杨幂"/>
</bean>
- 直接通过构造器参数名赋值
<bean id="UserDaoImpl" class="com.wu.dao.UserDaoImpl">
<constructor-arg name="username" value="迪丽热巴"/>
</bean>
总结:在配置文件家族的额时候,容器中管理的对象以及初始化了
4. Spring配置
4.1 别名
<bean id="UserDaoImpl" class="com.wu.dao.UserDaoImpl">
<property name="username" value="杨幂"/>
</bean>
<alias name="UserDaoImpl" alias="user"/>
4.2 Bean的配置
<!-- id:bean的唯一标识符
class:bean对象对应的全限类名
name:别名,可同时取多个-->
<bean id="UserDaoImpl" class="com.wu.dao.UserDaoImpl">
<property name="username" value="杨幂"/>
</bean>
4.3 import
- 一般用于团队开发,它可以将多个配置文件导入合并为一个
<import resource="ApplicationContext.xml"/>
5. 依赖注入
5.1 构造器注入
前面写过
5.2 Set方式注入
- 依赖注入:Set注入
- 依赖:bean对象的创建依赖与容器
- 注入:bean对象的所有属性由容器注入
1.实体类
@Getter
@Setter
@ToString
public class Student {
private String name;
private String empty;
private UserDaoImpl userDao;
private String [] books;
private List<String> hobbys;
private Map<String,String> userMaps;
private Set<String> userSet;
private Properties properties;
}
2.beans.xml
<?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">
<bean id="userDao" class="com.wu.dao.UserDaoImpl"></bean>
<bean id="Student" class="com.wu.pojo.Student">
<!-- 基本数据类型注入-->
<property name="name" value="赵丽颖"/>
<!-- null值注入-->
<property name="empty">
<null></null>
</property>
<!-- 引用类型注入-->
<property name="userDao" ref="userDao"/>
<!-- 数组注入-->
<property name="books">
<array>
<value>a</value>
<value>b</value>
<value>c</value>
</array>
</property>
<!-- list集合注入-->
<property name="hobbys">
<list>
<value>篮球</value>
<value>足球</value>
<value>乒乓球</value>
</list>
</property>
<!-- map集合注入-->
<property name="userMaps">
<map>
<entry key="杨幂" value="18"/>
<entry key="赵丽颖" value="28"/>
</map>
</property>
<!-- set集合注入-->
<property name="userSet">
<set>
<value>Lisi</value>
<value>wuwu</value>
</set>
</property>
<!-- Property对象注入-->
<property name="properties">
<props>
<prop key="url" >com:mysql:///</prop>
<prop key="username" >root</prop>
<prop key="password" >timi</prop>
</props>
</property>
</bean>
</beans>
3.测试类
@Test
public void beanTest(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) applicationContext.getBean("Student");
System.out.println(student);
}
5.3 扩展方式注入
使用命名空间注入需要在bean.xml文件中引入:
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
- p命名空间注入:
<!-- p命名空间注入,可以直接注入属性值:property-->
<bean id="userDao" class="com.wu.dao.UserDaoImpl" p:username="lisi"></bean>
- c命名空间注入:
<!-- c命名空间,通过构造器注入:constructor-->
<bean id="userDao" class="com.wu.dao.UserDaoImpl" c:username="刘思"></bean>
5.4 Bean的作用域
- singleton:单例模式(spring默认)只注入一个对象
<bean id="userDao" class="com.wu.dao.UserDaoImpl" c:username="刘思" scope="singleton"></bean>
- prototype:原型模式:每次getBeans是就创建一个新对象
<bean id="userDao" class="com.wu.dao.UserDaoImpl" c:username="刘思" scope="prototype"></bean>
- request:web开发有效
- session:web开发有效
- application:web开发有效
- websocket:web开发有效
6. Bean自动装配
- 自动装配是spring满足bean依赖的一种方式
- spring会在上下文中自动寻找,并自动给bean装配属性
在Spring中有三中装配方式:
- 在xml中显示的配置
- 在java中显示配置
- 隐式的自动装配bean(重点)
6.1 测试
- pojo类
@Setter
@ToString
public class Fruit {
private String grand;
private Banner banner;
private Apple apple;
}
- ByName自动装配:
<!-- autowire的byName属性自动在容器上下文查找和自己对象set方法后面的值对应的beanId-->
<bean id="fruit" class="com.wu.pojo.Fruit" autowire="byName">
<property name="grand" value="china"/>
</bean>
<bean id="apple" class="com.wu.pojo.Apple">
<property name="name" value="苹果"/>
</bean>
3.ByType自动装配
<!-- autowire的byType属性自动在容器上下文查找和自己对象属性类型相同的bean-->
<bean id="fruit" class="com.wu.pojo.Fruit" autowire="byType">
<property name="grand" value="china"/>
</bean>
<bean id="apple" class="com.wu.pojo.Apple">
<property name="name" value="苹果"/>
</bean>
小结:
- byname时,需要保证所有的bean的id唯一,并且这个bean需要和自动注入属性的set方法一致。
- bytype时,需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性一致。
6.2 注解自动装配
- 导入约束:context约束
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/context http://www.springframework.org/schema/context/spring-context.xsd "
- 配置注解的支持:
<!-- 注解配置,注解生效-->
<context:annotation-config></context:annotation-config>
- @Autowired
- 直接在属性上使用,也可以在set方法上使用
- 使用Autowired可以不用编写set方法,前提是自动装配的属性在IOC容器中存在。
- @Autowired默认依据属性的类型从spring容器中寻找对应bean对象注入,如果spring容器中存在多个相同的bean对象需要结合@Qualifier(value=“id名”)指定唯一的bean对象注入
- 也可以使用@Resource(name=“id名”)替代@Autowired和@Qualifier
7. 使用注解开发
在spring4之后使用注解开发必须导入aop依赖,使用注解需要导入context约束,还需要配置注解支持。
<?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: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/context http://www.springframework.org/schema/context/spring-context.xsd ">
<!-- 注解配置,注解生效-->
<context:annotation-config></context:annotation-config>
<!-- 扫描注解-->
<context:component-scan base-package="com.wu"/>
</beans>
- @Component:组件,放在类上,标志这个类被spring管理,就是bean,@Dao,@Service,@Controller效果一样
- bean
- 属性如何注入
@Component
@ToString
public class Dog {
@Value("小王")
private String name;
@Value("2")
private int age;
public void song(){
System.out.println("汪汪");
}
}
- 衍生的注解,功能都是将对象注入spring容器,装配bean
- @Dao
- @Service
- @Controller
- 自动装配
- 作用域:@Scope(“prototype”)
- 小结
xml与注解:- xml更加万能,适用于任何场合,维护简单
- 注解不是自己的类无法使用,维护相对比较复杂
- xml用来管理bean
- 注解只负责完成属性的注入
- 使用前提:需要让注解生效
<?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: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/context http://www.springframework.org/schema/context/spring-context.xsd ">
<!-- 注解配置,注解生效-->
<context:annotation-config></context:annotation-config>
<!-- 扫描注解-->
<context:component-scan base-package="com.wu"/>
</beans>
8.使用java的方式配置Spring
- 不使用spring的xml配置,全权交给java处理,JavaConfig是spring的一个子项目,在spring4之后成为核心功能。
实体类:
@ToString
public class Cat {
@Value("tom")
private String name;
@Value("2")
private String age;
}
java配置类
//@Configuration代表配置类,spring的配置注解,将类对象注入到容器,相当就是一个@Component
@Configuration
@ComponentScan("com.wu.pojo")
public class CatConfig {
// 注册一个bean,方法名相当与bean标签的id属性,方法的返回值相当与bean标签的class属性
@Bean
public Cat getCat(){
return new Cat();
}
}
测试类:
@Test
public void testConfigurate(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(CatConfig.class);
Object cat = applicationContext.getBean("getCat");
System.out.println(cat);
}
9. 代理模式
1. 静态代理:
+ 静态代理角色分析:
- 抽象角色:一般会使用接口或抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理真实角色,一般会做一些附属操作
- 客户:访问代理对象的人
代理模式的优点: - 可以让真实角色的操作更加纯粹,不用关注一些公共的业务
- 公共部分交给代理角色,实现业务分离
- 公共业务发生扩展时,方便集中管理
缺点: - 一个真实角色就产生一个代理对象,代码量翻倍,开发效率低下。
静态代理相当与service层调用dao层的对象进行业务逻辑操作
2.动态代理
- 动态代理和静态代理角色一样
- 动态代理的代理类是动态生成的,不是我们直接写好的
- 动态代理分为2大类, 基于接口的动态代理,基于类的动态代理
- 基于接口:JDK动态代理
- 基于类:cglib动态代理
- java字节码实现:javasist
关键类:Proxy:代理类,生成代理对象;InvocationHandler:调用处理类接口
代码实现:
接口:
public interface Rent {
void sing();
}
被代理的类:
public class Host implements Rent {
public void sing() {
System.out.println("狗在叫");
}
}
动态生成代理对象的类,实现InvocationHandler接口:
//自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
public void setRent(Rent rent) {
this.rent = rent;
}
//被代理的接口
private Object rent;
//生成得到代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
}
// 处理代理实例并返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 动态代理的本质就是利用反射机制实现
System.out.println("方法增强");
Object invoke = method.invoke(rent, args);
System.out.println("日志信息");
return invoke;
}
}
测试代码:
public class Client {
public static void main(String[] args) {
ProxyInvocationHandler handler = new ProxyInvocationHandler();
Host host=new Host();
// 设置需要代理的对象
handler.setRent(host);
//获取动态生成的代理对象
Rent proxy = (Rent) handler.getProxy();
proxy.sing();
}
}
一个动态代理类代理的是一个接口,一般对应一类业务
一个动态代理类可以代理多个类,只需要实现了相同的接口
10. AOP
1.AOP概念
- 面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。
- AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。
- 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
2.AOP在Spring中的作用
- Aspect: Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
- Joint point:表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。与切入点匹配的执行点。
- Pointcut:表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。
- Advice:Advice 定义了在 pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。类中的一个方法。
- Target:被通知的对象
Spring支持的5种类型的Advice:
通知的5种类型:执行顺序:相同类型已配置顺序为准
- before:前置通知<aop:before method=“before” pointcut-ref=“pt”/>
- after:后置通知<aop:after method=“after” pointcut-ref=“pt”/>
- afterReturning:环绕通知,返回后加入,有异常不执行<aop:after-returning method=“afterReturning” pointcut-ref=“pt”/>
- afterThrowing:异常抛出通知,有异常才会执行<aop:after-throwing method=“afterThrowing” pointcut-ref=“pt”/>
5 .round:引介通知,<aop:around method=“round” pointcut-ref=“pt”/>
3.使用Spring实现AOP
- 使用AOP织入,需要导入依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
方式一.;使用spring原生的api接口
- 接口:
public interface UserService {
void add();
void delete();
void update();
void select();
}
- 接口实现类:
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("添加数据");
}
public void delete() {
System.out.println("删除数据");
}
public void update() {
System.out.println("修改数据");
}
public void select() {
System.out.println("查询数据");
}
}
- spring原生api接口实现方法增强:
public class AfterLog implements AfterReturningAdvice {
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("环绕通知"+method.getName()+",返回结果为:"+returnValue);
}
}
public class BeforeLog implements MethodBeforeAdvice {
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("前置方法"+method.getName()+"执行了");
}
}
- xml文件配置:
<!-- 注册bean-->
<bean id="userService" class="com.wu.service.UserServiceImpl"/>
<bean id="beforeLog" class="com.wu.log.BeforeLog"/>
<bean id="afterLog" class="com.wu.log.AfterLog"/>
<!--方式一:使用spring原生的api接口-->
<!-- 配置aop,需要导入对应约束 -->
<aop:config>
<!-- 切入点:expression:表达式:execution(要执行的位置)-->
<aop:pointcut id="pointcut" expression="execution(* com.wu.service.UserServiceImpl.*(..))"/>
<!-- 执行环绕增强-->
<aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
- 测试
@Test
public void testAop(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理代理的是接口
UserService userService = applicationContext.getBean("userService", UserService.class);
userService.add();
}
方式二:自定义类
- 自定义切面类:
public class DiyLog {
public void before(){
System.out.println("自定义类前置增强方法");
}
public void after(){
System.out.println("自定义类后置增强方法");
}
}
- xml配置
<!-- 方式二:自定义切面类-->
<bean id="diyLog" class="com.wu.log.DiyLog"/>
<aop:config>
<!-- 自定义切面,ref:需要引入的增强类-->
<aop:aspect ref="diyLog">
<!-- 切入点-->
<aop:pointcut id="pointcut" expression="execution(* com.wu.service.UserServiceImpl.*(..))"/>
<!-- 通知:增强类中的增强方法-->
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after method="after" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
方式三:使用注解实现
- 自定义类:
Component
//声明切面类
@Aspect
public class DiyLog {
// 使用 @Pointcut 来声明切入点表达式.后面的其他通知直接使用方法名来引用当前的切入点表达式.
@Pointcut("execution(* com.wu.service.UserServiceImpl.*(..))")
public void common(){
}
// 声明前置通知和切入点
@Before("common()")
public void before(){
System.out.println("自定义类前置增强方法");
}
// 声明后置通知和切入点
@After("common()")
public void after(){
System.out.println("自定义类后置增强方法");
}
}
- xml配置
<!-- 注解配置,注解生效-->
<context:annotation-config></context:annotation-config>
<!-- 扫描注解-->
<context:component-scan base-package="com.wu"/>
<!-- 方式三:使用注解实现-->
<!-- 开启注解支持. JDK(默认 proxy-target-class="false",属性设置为true则是cglib) -->
<aop:aspectj-autoproxy proxy-target-class="false"/>
11.整合Mybatis
方式一
步骤:
1. 导入jar包
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.3</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.3</version>
</dependency>
</dependencies>
2.编写接口:
public interface BookCaseMapper {
List<BookCase> selectBookCaseList();
}
实现类:
@Setter
public class BookCaseMapperImpl implements BookCaseMapper {
private SqlSession sqlSession;
public List<BookCase> selectBookCaseList() {
return sqlSession.getMapper(BookCaseMapper.class).selectBookCaseList();
}
}
BookCaseMapper.xml:
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wu.dao.BookCaseMapper">
<select id="selectBookCaseList" resultType="bookCase">
select * from bookcase
</select>
</mapper>
3. 编写配置文件
mybatis.xml:
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--特别注意:
MyBatis中的配置,不但有类型限制,还有顺序限制
必须按照:<properties>、<settings>、<typeAliases>、<typeHandlers>、…顺序排放。-->
<configuration>
<!-- 1.properties属性引入外部配置文件 -->
<properties resource="db.properties"> </properties>
<typeAliases>
<typeAlias type="com.wu.pojo.BookCase" alias="bookCase"/>
</typeAliases>
<!-- <environments default="development">-->
<!-- <environment id="development">-->
<!-- <transactionManager type="JDBC"/>-->
<!-- <dataSource type="POOLED">-->
<!-- <property name="driver" value="${jdbc.driver}"/>-->
<!-- <property name="url" value="${jdbc.url}"/>-->
<!-- <property name="username" value="${jdbc.username}"/>-->
<!-- <property name="password" value="${jdbc.password}"/>-->
<!-- </dataSource>-->
<!-- </environment>-->
<!-- </environments>-->
<!-- <!– 每一个Mapper.xml都需要在Mybatis核心配置文件中注册–>-->
<!-- <mappers>-->
<!-- <mapper resource="mapper/BookCaseMapper.xml"/>-->
<!-- </mappers>-->
</configuration>
spring-dao.xml:
<?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: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/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 导入数据库配置文件-->
<context:property-placeholder location="db.properties"/>
<!-- 配置数据源:dataSource:使用spring的数据源代替mybatis的配置 c3p0 dbcp druid
使用spring提供的jdbc.datasource-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- SqlSessionFactory: rg.mybatis.spring.SqlSessionFactoryBean-->
<bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 绑定mybatis配置文件-->
<property name="configLocation" value="classpath:mybatis.xml"/>
<property name="mapperLocations" value="classpath:mapper/*Mapper.xml"/>
</bean>
<!-- SqlSessionTemplate:就是mybatis中的SqlSession-->
<bean id="SqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!-- 只能使用构造器注入SqlSessionFactory,因为SqlSessionTemplate没有set方法-->
<constructor-arg index="0" ref="SqlSessionFactory"/>
</bean>
</beans>
也可以采用多个配置文件开发:applicationContext.xml
<?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">
<import resource="classpath:spring-dao.xml"/>
<bean id="BookCaseMapperImpl" class="com.wu.dao.BookCaseMapperImpl">
<property name="sqlSession" ref="SqlSession"/>
</bean>
</beans>
5. 测试
@Test
public void Test2(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-dao.xml");
BookCaseMapperImpl bookCaseMapper = applicationContext.getBean(BookCaseMapperImpl.class);
List<BookCase> bookCases = bookCaseMapper.selectBookCaseList();
System.out.println(bookCases);
}
方式二
实现类:
//方式二
public class BookCaseMapperImpl extends SqlSessionDaoSupport implements BookCaseMapper {
public List<BookCase> selectBookCaseList() {
return getSqlSession().getMapper(BookCaseMapper.class).selectBookCaseList();
}
}
spring-dao.xml:
<!--如果mybatis整合使用方式二,省略以下内容-->
<!-- SqlSessionTemplate:就是mybatis中的SqlSession-->
<bean id="SqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!-- 只能使用构造器注入SqlSessionFactory,因为SqlSessionTemplate没有set方法-->
<constructor-arg index="0" ref="SqlSessionFactory"/>
</bean>
applicationContext.xml:
<!-- 方式二-->
<bean id="BookCaseMapperImpl" class="com.wu.dao.BookCaseMapperImpl">
<property name="sqlSessionFactory" ref="SqlSessionFactory"/>
</bean>
12.声明式事务
1.事务概念
- 把一组操作作为一个业务,要么同时成功,要么同时失败
- 事务在项目开发中,十分重要,涉及数据一致性问题
- 确保数据的完整性和一致性
事务的ACID原则
- 原子性
- 一致性
- 隔离性:多个业务可能操作同一个资源,防止数据损坏
- 永久性:事务一旦提交,就会被持久化写入存储器。
2. 事务管理
- 编程式事务
- 声明式事务
- spring-dao.xml配置
<!--配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 结合aop实现事务织入
配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 给方法配置事务-->
<!-- 配置事务的传播特性 propagation=""-->
<tx:attributes>
<!-- name为方法名,*:代表所有方法-->
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="updateById" propagation="REQUIRED"/>
<tx:method name="select" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 配置事务织入-->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.wu.dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
2.实现类:
public class BookCaseMapperImpl extends SqlSessionDaoSupport implements BookCaseMapper {
public List<BookCase> selectBookCaseList() {
add(new BookCase(22,"爱情片"));
updateById(new BookCase(20,"动漫"));
return getSqlSession().getMapper(BookCaseMapper.class).selectBookCaseList();
}
public int add(BookCase bookCase) {
return getSqlSession().getMapper(BookCaseMapper.class).add(bookCase);
}
public int updateById(BookCase bookCase) {
return getSqlSession().getMapper(BookCaseMapper.class).updateById(bookCase);
}
}
3.测试类:
@Test
public void Test2(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
BookCaseMapper bookCaseMapper = applicationContext.getBean(BookCaseMapper.class);
List<BookCase> bookCases = bookCaseMapper.selectBookCaseList();
System.out.println(bookCases);
}
注意采用aop事务织入时spring默认jdk基于接口的动态代理,必须获取接口的class,而不应该是实现类的bean
3. 为什么需要配置事务:
- 如果不配置事务,可能会存在数据提交不一致问题
- 如果不在spring中配置事务,我们需要在代码中手动配置
- 事务在项目开发中十分重要,保证事务的ACID原则。