Spring
HNU Peter Lv2

Spring

1、简介

目的:简化企业级应用开发的复杂性。

maven依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.18</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.18</version>
</dependency>

1.1、特点:

  • Spring是一个开源的免费容器;
  • 是一个非轻量级、非入侵式(不影响原本内容)的框架;
  • **==控制反转(IOC),面向切面编程(AOP)==**;
  • 支持事务处理,整合框架。

1.2、组成

image-20220508124245908

2、IOC控制反转

将service层的实现接口加上setDao方法,由用户自定义传入参数确定应该使用Dao接口的具体实现类:

==使用set注入:==

1
2
3
4
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}

此时,程序猿不再需要管理对象的创建,而交给用户自定义!并且使系统的耦合性大大降低

控制反转IoC(Inversion of Conotrol)是一种设计思想,DI(依赖注入)是实现IoC的一种方法。

IoC是Spring框架的核心内容(通过xml配置管理对象)。

2.1 HelloSpring

pojo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.pans.pojo;

public class Hello {
private String str;

public String getStr() {
return str;
}

public void setStr(String str) {
this.str = str;
}

@Override
public String toString() {
return "Hello{" +
"str='" + str + '\'' +
'}';
}
}

beans.xml

1
2
3
4
5
6
7
8
9
<?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">
<!--使用Spring创建对象-->
<bean class="com.pans.pojo.Hello" id="hello">
<property name="str" value="Hello Spring!"/>
</bean>
</beans>

test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {

public static void main(String[] args) {
//获取Spring上下文对象
ApplicationContext applicationContext= new ClassPathXmlApplicationContext("beans.xml");
//所有的对象都在Spring容器中,直接去容器中区即可
Object hello = applicationContext.getBean("hello");
System.out.println(hello);

}
}

3、IoC创建对象的方式

  • 默认用无参构造!

有参构造方式:

  1. 下标构造
1
2
3
public Hello(String str) {
this.str = str;
}
1
2
3
<bean class="com.pans.pojo.Hello" id="hello">
<constructor-arg index="0" value="Hello Spring"/>
</bean>
  1. type类型构造(不建议使用,相同时按顺序构造)
  2. ref引用类型
  3. 参数名(最常用)

在配置文件被加载时,配置文件里面的所有类都会被初始化,并且同一个类只拥有一个对象!

1
2
3
Object hello = applicationContext.getBean("hello");
Object hello2 = applicationContext.getBean("hello");
System.out.println(hello.equals(hello2)); //true

4、Spring配置

  • 别名
  • bean配置
  • import

5、DI(依赖注入)

Dependency Injection

5.1 构造器注入

5.2 set注入(重点)

  • bean对象的创建依赖容器
  • bean对象中的所有属性,由容器注入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?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 class="com.pans.pojo.Address" id="address">
<property name="address" value="重庆"/>
</bean>
<bean class="com.pans.pojo.Student" id="student">
<!-- 第一种:普通属性注入-->
<property name="name" value="Peter~"/>
<!-- 第二种:bean注入,ref-->
<property name="address" ref="address"/>
<!-- 第三种:数组注入-->
<property name="books">
<array>
<value>红楼梦</value>
<value>西游记</value>
<value>三国演绎</value>
</array>
</property>
<!-- list注入-->
<property name="hobbies">
<list>
<value>听歌</value>
<value>敲代码</value>
<value>打游戏</value>
</list>
</property>
<!-- map注入-->
<property name="card">
<map>
<entry key="身份证" value="12412412"/>
<entry key="学生证" value="432432423"/>

</map>
</property>
<!-- set集合注入-->
<property name="games">
<set>
<value>LOL</value>
<value>LPL</value>
<value>DOTA</value>
</set>
<!-- null注入-->
</property>
<property name="wife">
<null/>
</property>
<!-- properties属性注入-->
<property name="info">
<props>
<prop key="学号">2021123123</prop>
<prop key="姓名">张三</prop>
<prop key="性别"></prop>


</props>
</property>

</bean>

</beans>

5.3 其他方式

c命名空间注入和p命名空间注入(必须在命名约束里面引入约束代码)

1
2
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
1
<bean class="com.pans.pojo.Address" p:address="重庆"/>

5.3 bean作用域

  1. 单例模式(默认)
1
2
<!--默认单例模式-->
<bean class="com.pans.pojo.Student" id="student" scope="singleton">
  1. 原型模式

每次从容器中get的时候,都会产生一个新的对象。

1
2
<!--原型模式-->
<bean class="com.pans.pojo.Student" id="student" scope="prototype">
  1. 其余的request,session,application只能在web开发中使用。

6、Bean的自动装配

  • 自动装配式Spring满足bean依赖的一种方式!
  • Spring会在上下文中自动寻找并自动给bean装配属性!

6.1 Spring中的三种装配方式:

  1. 在xml中显式配置
  2. 在java中显式配置
  3. ==隐式自动装配bean!!==

byName:(id必须全局唯一)

会在容器上下文中自动寻找和自己对象set方法后面的值对应的id

1
2
3
4
5
6
7
8
<bean class="com.pans.pojo.Dog" id="dog"/>
<bean class="com.pans.pojo.Cat" id="cat"/>

<bean class="com.pans.pojo.People" id="people" autowire="byName">
<property name="name" value="peters!!!"/>

</bean>

byType:(可省略id,对象属性必须唯一)

会在容器上下文中自动寻找和自己对象属性相同的bean

1
2
3
4
5
6
7
8
<bean class="com.pans.pojo.Dog"/>
<bean class="com.pans.pojo.Cat"/>

<bean class="com.pans.pojo.People" id="people" autowire="byType">
<property name="name" value="peters!!!"/>

</bean>

6.2 使用注解实现自动装配

  1. 导入约束和配置注解的支持
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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/>

<bean id="dog" class="com.pans.pojo.Dog"/>
<bean id="cat" class="com.pans.pojo.Cat"/>

<bean class="com.pans.pojo.People" id="people"/>
</beans>
  1. 在实体类里面添加注解(属性或者se方法上都可以)
1
2
3
4
5
public class People {
@Autowired
private Cat cat;
@Autowired
private Dog dog;

@Autowired

  • 可以不使用set方法了,前提是自动装配的属性在IOC容器中存在,且符合名字byName

  • 可以添加(required=false)表示此字段可以为空

  • 默认byType,当Type不止一个时,可以通过注解Qualifier指定byName

1
2
3
@Autowired
@Qualifier(value = "cat2")
private Cat cat;
  1. Resource也可以用于自动装配

区别:Autowired默认通过byType实现,Resource默认byName实现,当byName找不到则通过byType实现

7、使用纯Java注解配置Spring

实体类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.pans.dao;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component //可加可不加
public class UserDao {
@Value("peters~")
private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "UserDao{" +
"name='" + name + '\'' +
'}';
}
}

配置bean类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.pans.Config;

import com.pans.dao.UserDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class UserConfig {

@Bean
public UserDao userDao(){
return new UserDao();
}
}

测试类:

1
2
3
4
5
6
7
8
9
10
11
12
13
import com.pans.Config.UserConfig;
import com.pans.dao.UserDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Mytest {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(UserConfig.class);
UserDao getName = context.getBean("userDao", UserDao.class);
System.out.println(getName);
}
}

8、代理模式

代理模式是SpringAOP的底层!

分类:

  • 静态代理
  • 动态代理

image-20220511103827491

8.1 静态代理

角色分析:

  • 抽象角色:一般使用接口或者抽象类解决(租房)
  • 真实角色:被代理的角色(房东 )
  • 代理角色:代理真实角色,代理真实角色后会有更多附属操作!(中介)
  • 客户:访问代理对象的人

代码示例:

1
2
3
interface  Rent {
public void rent();
}
1
2
3
4
5
6
//房东
public class Host implements Rent {
public void rent(){
System.out.println("签合同,出租房屋!");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//中介
public class Middle {
private Host host;

public Middle(Host host) {
this.host = host;
}

public Middle() {
}

//出租房屋
public void rent(){
host.rent();
}
//中介可以用其他附属操作
public void lookOther(){
System.out.println("带客户看房!");
}
}
1
2
3
4
5
6
7
8
9
10
//客户
public class Renter {
public static void main(String[] args) {
Host host = new Host();
Middle middle = new Middle(host);
middle.rent();
middle.lookOther();

}
}

好处:

  • 是真实角色(房东)更加简洁,不需要关注一些复杂的业务,交给代理角色实现
  • 公共业务方便扩展和集中管理

缺陷:

  • 一个真实角色需要一个代理角色,代码量大,开发效率变低!

8.2 浅聊AOP

开闭原则:对修改关闭,对扩展开放!(尽量不去改动原有业务代码,而是通过加入新的业务添加新的功能并且代理原有业务实现业务扩展)

image-20220511111532172

8.3 动态代理

  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的!
  • 动态代理分为两大类︰基于接口的动态代理,基于类的动态代理
    • 基于接口—- JDK动态代理【我们在这里使用】
    • 基于类: cglib
    • java字节码实现 : javassist

jdk动态代理由反射实现,主要关注类Proxy和接口

9、AOP

AOP在程序员不必改变原有代码的情况下,去横向增加新的功能!

9.1 AOP的Spring实现方式一

使用Spring自带API

  1. 先导入aop依赖
1
2
3
4
5
6
7
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
<scope>runtime</scope>
</dependency>
  1. 代理服务接口
1
2
3
4
5
6
7
8
package com.pans.service;

public interface UserService{
public void add();
public void delete();
public void update();
public void query();
}
  1. 代理服务接口实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.pans.service;

public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("调用了add方法");
}

@Override
public void delete() {
System.out.println("调用了delete方法");

}

@Override
public void update() {
System.out.println("调用了update方法");
}

@Override
public void query() {
System.out.println("调用了query方法");
}
}
  1. aop增加服务1(前服务)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.pans.Log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class BeforeLog implements MethodBeforeAdvice {
//Method:要执行的目标对象的方法
//args: 参数
//target:目标对象
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"方法被执行了");
}
}
  1. aop增加服务2(后服务)
1
2
3
4
5
6
7
8
9
10
11
12
package com.pans.Log;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class AfterLog implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"方法被执行了"+",返回值为"+returnValue);
}
}
  1. beans.xml注册服务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

<bean class="com.pans.service.UserServiceImpl" id="service"/>
<bean class="com.pans.Log.AfterLog" id="afterLog"/>
<bean class="com.pans.Log.BeforeLog" id="beforeLog"/>

<!-- 配置aop,需要导入aop模块-->
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.pans.service.UserServiceImpl.*(..))"/>

<!-- 执行切入点-->
<aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>

</aop:config>
</beans>
  1. 测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import com.pans.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Mytest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
// 通过接口实现动态代理
UserService userService = context.getBean("service", UserService.class);
userService.add();
userService.delete();
userService.update();
userService.query();
}
}

9.2 AOP的Spring实现方式二

使用自定义类

1
2
3
4
5
6
7
8
public class Log {
public void before(){
System.out.println("方法执行前!");
}
public void after(){
System.out.println("方法执行后!");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
<!--    使用自定义类-->
<bean class="com.pans.Log.Log" id="log"/>
<aop:config>
<!-- 自定义切面-->
<aop:aspect ref="log">
<!-- 切入点-->
<aop:pointcut id="point" expression="execution(* com.pans.service.UserServiceImpl.*(..))"/>
<!-- 通知-->
<aop:before method="before" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
</aop:aspect>
</aop:config>

9.3 AOP的Spring实现方式三

使用注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect //这里如果不行请注意更改pom.xml中依赖的scope作用域
public class Log {
@Before("execution(* com.pans.service.UserServiceImpl.*(..))")
public void before(){
System.out.println("方法执行前!");
}
@After("execution(* com.pans.service.UserServiceImpl.*(..))")
public void after(){
System.out.println("方法执行后!");
}
}

xml中配置开启注解支持

1
2
3
4
<!--    方式三:设置注解支持-->
<bean class="com.pans.Log.Log"/>
<!-- 开启注解支持-->
<aop:aspectj-autoproxy/>

10、整合Mybatis

10.1 回顾Mybatis用法

image-20220512123147077

  1. 编写实体类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package com.pans.pojo;


public class User {

private long id;
private String name;
private String pwd;
private String teacherId;


public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}


public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}


public String getPwd() {
return pwd;
}

public void setPwd(String pwd) {
this.pwd = pwd;
}


public String getTeacherId() {
return teacherId;
}

public void setTeacherId(String teacherId) {
this.teacherId = teacherId;
}

public User(long id, String name, String pwd, String teacherId) {
this.id = id;
this.name = name;
this.pwd = pwd;
this.teacherId = teacherId;
}

@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
", teacherId='" + teacherId + '\'' +
'}';
}
}
  1. 编写mapper接口
1
2
3
4
5
6
7
8
9
package com.pans.Mapper;

import com.pans.pojo.User;

import java.util.List;

public interface UserMapper {
public List<User> query();
}
  1. 编写接口实现
1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pans.Mapper.UserMapper">
<select id="query" resultType="user">
select * from user;
</select>
</mapper>
  1. 配置mybatis-config.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="com.pans.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf-8&amp;serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/pans/Mapper/UserMapper.xml"/>
</mappers>
</configuration>
  1. 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class MybatisTest {
@Test
public void test() throws IOException {
String resource = "Mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();

UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> query = mapper.query();
for (User user : query) {
System.out.println(user);
}
}
}

10.2 Mybatis-Spring

  1. 编写数据源配置
  2. sqlSessionFactory
  3. sqlSessionTemplate
  4. 需要给接口增加实现类
  5. 将实现类注入到Spring中测试
  • 直接在配置文件中配置sqlSession,简化测试类为:
1
2
3
4
5
6
7
ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");

UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
List<User> query = userMapper.query();
for (User user : query) {
System.out.println(user);
}
  • mybatis-config简化为:
1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="com.pans.pojo"/>
</typeAliases>
</configuration>

image-20220512160734501

  • mapper增加实现类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.pans.Mapper;

import com.pans.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;

import java.util.List;

public class UserMapperImpl implements UserMapper {
private SqlSessionTemplate sqlSession;

// 在Spirng中注入
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
//在Spring中注册实现类
@Override
public List<User> query() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.query();
}
}
  • 配置专门处理sqlSession的xml文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?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 class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf-8&amp;serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>

<!-- sqlSessioinFactory-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
<property name="dataSource" ref="dataSource"/>
<!-- 绑定mybatis配置文件-->
<property name="configLocation" value="classpath:Mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:com/pans/Mapper/UserMapper.xml"/>
</bean>

<!-- SqlSessionTemplate即是我们的sqlSession -->
<bean class="org.mybatis.spring.SqlSessionTemplate" id="sqlSession">
<!-- 只能通过构造器方法注入,以为它没有set方法-->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>

</beans>
  • spring-dao.xml:
1
2
3
4
5
6
7
8
9
10
11
12
<?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="appkicationContext.xml"/>

<bean class="com.pans.Mapper.UserMapperImpl" id="userMapper">
<property name="sqlSession" ref="sqlSession"/>
</bean>

</beans>

11、Spring中的事务管理

  • 声明式事务:AOP
  • 编程式事务:需要在代码中进行事务管理(需修改原有代码,不推荐)
  1. mapper接口中添加方法
1
2
3
4
5
6
7
8
9
10
11
import com.pans.pojo.User;

import java.util.List;

public interface UserMapper {
public List<User> query();

public int add(User user);

public int delete(int id);
}
  1. mapper实现类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.pans.Mapper;

import com.pans.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;

import java.util.List;

public class UserMapperImpl implements UserMapper {
private SqlSessionTemplate sqlSession;

// 在Spirng中注入
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
//在Spring中注册实现类
@Override
public List<User> query() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

User user = new User(7, "潘帅", "sad", "sad");
mapper.add(user);
mapper.delete(7);
return mapper.query();
}


@Override
public int add(User user) {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.add(user);
}

@Override
public int delete(int id) {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.delete(id);
}
}

  1. mapper配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pans.Mapper.UserMapper">
<select id="query" resultType="user">
select * from user;
</select>

<insert id="add" parameterType="user">
insert into user (id,name,pwd) values(#{id},#{name},#{pwd})
</insert>

<delete id="delete" parameterType="int">
deletes from user where id=#{id};
</delete>

</mapper>
  1. spring的xml配置中增加事务支持
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!--    配置声明式事务-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<constructor-arg ref="dataSource"/>
</bean>

<!-- 结合AOP实现事务的织入-->
<!-- 配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="query"/>
</tx:attributes>
</tx:advice>
<!-- 配置事务切入点-->
<aop:config>
<!-- 配置切入点-->
<aop:pointcut id="txPoint" expression="execution(* com.pans.Mapper.*.*(..))"/>
<!-- 启用切入点!!!-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"/>
</aop:config>