# spring-learn
**Repository Path**: hrbu2023/spring-learn
## Basic Information
- **Project Name**: spring-learn
- **Description**: spring-ioc、AOP学习
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-03-10
- **Last Updated**: 2026-03-13
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Spring Core
Spring使得创建Java企业级应用变得轻松。它提供了在企业环境中使用Java语言所需的一切功能,支持Groovy和Kotlin作为JVM上的替代语言,并具备根据应用需求灵活构建多种架构的能力。自Spring Framework 6.0起,Spring要求Java 17+版本
IOC 容器( Inversion of Control ): 控制翻转: 类与类之间的依赖关系,由工厂(容器)管理,被依赖的对象什么时候创建、怎么创建都交给Spring 工厂
- Controller
- Service
- Dao(Mapper)
public class UserController{
private IUserService userService = new UserService
- list
- save
- update
}
## 实例
项目名称-- spring-01-ioc-xml

在父项目中使用 dependencyManagement 统一定义 依赖的版本号方便统一修改管理
```xml
4.0.0
com.neuedu.sm
spring-learn
1.0
pom
spring-learn
http://maven.apache.org
spring-01-ioc-xml
UTF-8
5.13.4
org.junit.jupiter
junit-jupiter-api
${junit.version}
test
```
在父项目中 添加Spring的版本,然后在 01-ioc-xml项目中真正的添加依赖(不需要版本号)
### 父项目
```xml
4.0.0
com.neuedu.sm
spring-learn
1.0
pom
spring-learn
http://maven.apache.org
spring-01-ioc-xml
UTF-8
5.13.4
6.2.16
org.junit.jupiter
junit-jupiter-api
${junit.version}
test
org.springframework
spring-context
${spring.version}
org.springframework
spring-beans
${spring.version}
org.springframework
spring-core
${spring.version}
org.springframework
spring-expression
${spring.version}
```
### 子项目添加具体的依赖

使用UserService 依赖 UserDao 说明 IOC的关系
- IUserService : service层的接口
- UserServiceImpl : 实现IUserService 的实现类
- IUserDao : dao层的接口
- UserDaoImpl : 实现IUserDao 的实现类
创建工厂: 管理 IUserService 实例、IUserDao
从工厂中获取一个UserService 调用里面的方法
### 编写代码
实现使用工厂管理 UserService
IUserService
```java
package com.neuedu.sm.service;
public interface IUserService {
/**
* 查询用户列表
*/
public void list();
}
```
UserServiceImpl
```java
package com.neuedu.sm.service.impl;
import com.neuedu.sm.service.IUserService;
public class UserServiceImpl implements IUserService {
@Override
public void list() {
System.out.println("查询用户信息");
}
}
```
### 使用XML定义工厂
```xml
```
### 测试
从容器中获取对象(UserService)
使用XML文件的形式构造容器(工厂),使用ClassPathXmlApplicationContext 加载 xml 构建工厂

### 使用工厂
```
package com.neuedu.sm;
import com.neuedu.sm.service.IUserService;
import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UseBeanFactory {
@Test
public void test(){
//1 构造工厂
// "spring-ioc.xml" 配置文件
// context 工厂对象 : 作用 管理对象的全部生命周期(创建、销毁......)
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-ioc.xml");
//2 从工厂中获取对象
IUserService userService = context.getBean(IUserService.class);
System.out.println("userService = " + userService);
//3 调用对象 list方法
userService.list();
}
}
```
## 依赖注入(构造器子注入)
使用IOC容器管理Dao
- IUserDao
- UserDaoImpl
IUserDao
```java
package com.neuedu.sm.dao;
public interface IUserDao {
public void selectList();
}
```
UserDaoImpl
```java
package com.neuedu.sm.dao.impl;
import com.neuedu.sm.dao.IUserDao;
public class UserDaoImpl implements IUserDao {
@Override
public void selectList() {
System.out.println("UserDaoImpl.selectList 实现");
}
}
```
使用容器管理
```xml
```
维护依赖关系
UserService 需要使用UserDao
在容器配置文件中 给UserService 设置一个UserDao

```xml
```
## 依赖注入(设值注入 setter)
使用IOC容器管理Dao
- IRoleService
- RoleServiceImp;
- IRoleDao
- RoleDaoImpl
### IRoleService
```java
package com.neuedu.sm.service;
public interface IRoleService {
/**
* 查询角色列表
*/
public void list();
}
```
### RoleServiceImp
注意需要给注入的属性添加setter属性
```java
package com.neuedu.sm.service.impl;
import com.neuedu.sm.dao.IRoleDao;
import com.neuedu.sm.dao.IUserDao;
import com.neuedu.sm.service.IRoleService;
import com.neuedu.sm.service.IUserService;
public class RoleServiceImpl implements IRoleService {
private IRoleDao roleDao;
@Override
public void list() {
System.out.println("service 查询查询角色 信息");
roleDao.selectList();
}
public IRoleDao getRoleDao() {
return roleDao;
}
public void setRoleDao(IRoleDao roleDao) {
this.roleDao = roleDao;
}
}
```
### IRoleDao(Dao层)
```java
package com.neuedu.sm.dao;
public interface IRoleDao {
public void selectList();
}
```
### RoleDaoImpl
```java
package com.neuedu.sm.dao.impl;
import com.neuedu.sm.dao.IRoleDao;
import com.neuedu.sm.dao.IUserDao;
public class RoleDaoImpl implements IRoleDao {
@Override
public void selectList() {
System.out.println("RoleDaoImpl.selectList 实现");
}
}
```
### 声明依赖
```xml
```

### 单元测试(UseBeanFactory)
```java
@Test
public void testSetterDI(){
//1 构造工厂
// "spring-ioc.xml" 配置文件
// context 工厂对象 : 作用 管理对象的全部生命周期(创建、销毁......)
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-ioc.xml");
//2 从工厂中获取对象
IRoleService roleService = context.getBean(IRoleService.class);
//3 调用对象 list方法
roleService.list();
}
```
# 各种输入的属性类型
在类中注入常见的数据类型 int、String double、float long、array List Map Properties
## 可以被依赖注入的一个Bean类型
```java
package com.neuedu.sm.dao;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class DeptDao {
private String url;
private Integer maxConnection;
private double salary;
private String[] names;
private List users;
private Set ages;
private Map personInfo;
private Properties jdbcInfo;
//setter
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Integer getMaxConnection() {
return maxConnection;
}
public void setMaxConnection(Integer maxConnection) {
this.maxConnection = maxConnection;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String[] getNames() {
return names;
}
public void setNames(String[] names) {
this.names = names;
}
public List getUsers() {
return users;
}
public void setUsers(List users) {
this.users = users;
}
public Set getAges() {
return ages;
}
public void setAges(Set ages) {
this.ages = ages;
}
public Map getPersonInfo() {
return personInfo;
}
public void setPersonInfo(Map personInfo) {
this.personInfo = personInfo;
}
public Properties getJdbcInfo() {
return jdbcInfo;
}
public void setJdbcInfo(Properties jdbcInfo) {
this.jdbcInfo = jdbcInfo;
}
}
```
## 在容器中声明(管理)Bean对象

## 使用
```xml
张三
李四
王五
王五
张飞
刘备
李逵
李逵
100
25
33
33
jdbc:mysql://localhost:3306/his?chartxxxxx=utf-8
com.mysql.jdbc.cj.Driver
root
root
```
```java
package com.neuedu.sm.dao;
import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import static org.junit.jupiter.api.Assertions.*;
class DeptDaoTest {
/**
*
* DI dependency Injection 依赖注入
*/
@Test
public void testDI() {
//获取容器 工厂
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-ioc.xml");
//获取DeptDao
// DeptDao deptDao = (DeptDao) context.getBean("deptDao");
// DeptDao deptDao = context.getBean("deptDao", DeptDao.class);
DeptDao deptDao = context.getBean(DeptDao.class);
System.out.println(deptDao);
System.out.println("deptDao.getNames().length = " + deptDao.getNames().length);
}
}
```
## 控制台打印
```ini
DeptDao{url='jdbc:mysql://localhost:3306/his?chartxxxxx=utf-8', maxConnection=100, salary=500.02, names=[张三, 李四, 王五, 王五], users=[张飞, 刘备, 李逵, 李逵], ages=[100, 25, 33], personInfo={name=张三, age=25, sex=男}, jdbcInfo={jdbc.password=root, jdbc.user=root, jdbc.url=jdbc:mysql://localhost:3306/his?chartxxxxx=utf-8, jdbc.driver=com.mysql.jdbc.cj.Driver}}
deptDao.getNames().length = 4
Process finished with exit code 0
```
# 使用注解的形式声明Bean
- 在xml中使用 包扫描的方式声明Bean
```xml
```
在需要声明Bean的类上面使用 @Component注解
```java
package com.neuedu.sm.service;
import org.springframework.stereotype.Component;
/**
* 当包扫描的时候 需要在容器中注册Bean
* 作用同
*/
@Component
public class UserService {
public void list() {
System.out.println("UserService.list--Service层");
}
}
```
各种注解的含义
除了@Component这个泛指组件的注解外,Spring还提供了与@Component功能相同的三个语义化注解。
1. @Service 业务层组件
2. @Controller 控制层组件
3. @Repository 数据层组件
修改上面代码,使用@Repository 和 @Service 替换 dao 与 service 组件上的注解。
# 使用Autowired注入属性
基于注解的依赖 使用@Autowired注解,`@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})`
## 构造方法注入
```java
package com.neuedu.sm.controller;
import com.neuedu.sm.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
private UserService userService;
/**
* 构造器的方式注入
* @param userService
*/
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
public void queryList() {
System.out.println("UserController.queryList --Controller层");
userService.list();
}
}
```
## 属性注入
```java
package com.neuedu.sm.service;
import com.neuedu.sm.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
/**
* 当包扫描的时候 需要在容器中注册Bean
* 作用同
*/
@Service
public class UserService {
/**
* 属性注入
*/
@Autowired
private UserDao userDao;
public void list() {
System.out.println("UserService.list--Service层");
userDao.selectList();
}
/* public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}*/
}
```
```java
package com.neuedu.sm.dao;
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
public void selectList() {
System.out.println("UserDao.selectList 实现");
}
}
```
存在同一个类型 由多个实例
使用注解 Qualifier 按名称查找,

# Spring的测试框架
使用的框架 是 **Junit5** 在编写代码过程中经常的会测试 Bean,代码的逻辑是使用@BeforeEach的注解,获取容器,然后在从容器中获取Bean(Controller、Service、Dao等)
可以使用 Spring-test框架对 Junit进行扩展(自动启动容器-Bean工厂 ),然他默认加载某一个配置文件,可以使用@Autowired从容器中获取Bean
## 引入依赖
- Junit-4
- junit-5
- Spring-test
在父项目的pom.xml中声明依赖的版本
```xml
4.0.0
com.neuedu.sm
spring-learn
1.0
pom
spring-learn
http://maven.apache.org
spring-01-ioc-xml
spring-02-ico-xml-component-scan
spring-03-ico-xml-component-scan-DI
UTF-8
4.13.2
5.13.4
6.2.16
org.junit.jupiter
junit-jupiter-api
${junit.version}
test
junit
junit
${junit4.version}
test
org.springframework
spring-context
${spring.version}
org.springframework
spring-beans
${spring.version}
org.springframework
spring-core
${spring.version}
org.springframework
spring-expression
${spring.version}
org.springframework
spring-test
test
${spring.version}
```
## 创建一个子项目
spring-04-ioc-xml-scan-autowired-test-framework
子项目的依赖
```xml
4.0.0
com.neuedu.sm
spring-learn
1.0
spring-04-ioc-xml-scan-autowired-test-framework
jar
spring-04-ioc-xml-scan-autowired-test-framework
http://maven.apache.org
UTF-8
org.springframework
spring-context
org.springframework
spring-test
org.junit.jupiter
junit-jupiter-api
junit
junit
```
## 使用03的代码(Junit-5)
在单元测试类上添加 `@SpringJUnitConfig(locations = "classpath:spirng-ioc-scan-di.xml")` 会自动的注册Bean工厂,可以在当前的测试类中使用@Autowired从容器中获取 Bean
```java
package com.neuedu.sm.controller;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
//使用Spring-test 对 Junit的扩展
@SpringJUnitConfig(locations = "classpath:spirng-ioc-scan-di.xml")
class UserControllerJunit5Test {
@Autowired
UserController userController;
@Test
void queryList() {
userController.queryList();
}
}
```
## Junit4的支持
```java
package com.neuedu.sm.controller;
//import org.junit.jupiter.api.Test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
//使用Spring-test 对 Junit的扩展
//@SpringJUnitConfig(locations = "classpath:spirng-ioc-scan-di.xml")
//RunWith 对 Junit进行扩展
//@RunWith(value=SpringJUnit4ClassRunner.class)
//@ContextConfiguration(locations = "classpath:spirng-ioc-scan-di.xml")
//@ContextConfiguration(value = "classpath:spirng-ioc-scan-di.xml")
/**
* 使用Junit4
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spirng-ioc-scan-di.xml")
public class UserControllerJunit4Test {
@Autowired
UserController userController;
@Test
public void queryList() {
userController.queryList();
}
}
```
# Java配置类
## 普通的Bean声明
```java
public class UserController {
public void queryList(){
System.out.println("UserController.queryList --Controller层");
}
}
```
## 使用配置类的方式注册Bean(替代配置文件)
```java
package com.neuedu.sm;
import com.neuedu.sm.controller.UserController;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* 相当于配置文件
*
* Configuration
*/
public class SpirngIocConfiguration {
/**
* @Bean 相当与
*
* @Bean 一般用于注册第三方的 包(拿不到源码 )
* @return
*/
@Bean
public UserController userController() {
return new UserController();
}
}
```
## 使用@ComponentScan注解进行包扫描

# 使用@Bean注册第三方类
在容器中注册 Mybatis的SQLSessionFactory
- 添加依赖
- 父项目中版本控制
- 子项目中添加依赖(不需要版本号)
## 父项目的pom.xml
```xml
4.0.0
com.neuedu.sm
spring-learn
1.0
pom
spring-learn
http://maven.apache.org
spring-01-ioc-xml
spring-02-ioc-xml-component-scan
spring-03-ioc-xml-component-scan-DI
spring-04-ioc-xml-scan-autowired-test-framework
spring-05-javaconfig
UTF-8
4.13.2
5.13.4
6.2.16
8.2.0
3.5.19
org.junit.jupiter
junit-jupiter-api
${junit.version}
test
junit
junit
${junit4.version}
test
org.springframework
spring-context
${spring.version}
org.springframework
spring-beans
${spring.version}
org.springframework
spring-core
${spring.version}
org.springframework
spring-expression
${spring.version}
org.springframework
spring-test
test
${spring.version}
com.mysql
mysql-connector-j
${mysql.version}
org.mybatis
mybatis
${mybatis.version}
```
## 子项目添加依赖
```xml
4.0.0
com.neuedu.sm
spring-learn
1.0
spring-05-javaconfig
jar
spring-05-javaconfig
http://maven.apache.org
UTF-8
org.springframework
spring-context
org.springframework
spring-test
org.junit.jupiter
junit-jupiter-api
com.mysql
mysql-connector-j
org.mybatis
mybatis
```
# Bean的作用域
| Scope | Description |
| :---------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [singleton](https://docs.spring.io/spring-framework/reference/6.2/core/beans/factory-scopes.html#beans-factory-scopes-singleton) | (默认)将单个 Bean 定义映射到每个 Spring IoC 的单个对象实例 容器。 |
| prototype | 将单个豆定义作用域为任意数量的对象实例。 |
| request | 将单个 bean 定义作用域到单个 HTTP 请求的生命周期。也就是说, 每个HTTP请求都有自己由单个豆子创建的豆子实例 定义。仅在具备网页功能的 Spring 环境中有效。`ApplicationContext` |
| session | 将单个豆定义作用域到HTTP的生命周期。仅在 一个具备网络感知的春季环境。`Session``ApplicationContext` |
| application | 用单一豆子定义范围到一个的生命周期。仅在 一个具备网络感知的春季环境。`ServletContext``ApplicationContext` |
| [websocket](https://docs.spring.io/spring-framework/reference/6.2/web/websocket/stomp/scope.html) | 用单一豆子定义范围到一个的生命周期。仅在 网络感知春季的背景 `WebSocket``ApplicationContext`. |
# AOP 面相切面编程
## 代理机制
Spring AOP使用了两种代理机制:一种是基于JDK的动态代理;另一种是基于CGLib的动态代理。之所以需要两种代理机制,是因为JDK本身只提供接口的代理,而不支持类的代理。
### JDK动态代理
Spring的AOP的默认实现就是采用jdk的动态代理机制实现的。
自Java1.3以后,Java提供了动态代理技术,允许开发者在运行期创建接口的代理实例。
### CGLib代理
JDK只能为接口创建代理实例,对于那些没有通过接口定义业务方法的类,可以通过CGLib创建代理实例。
CGLib采用底层字节码技术,可以为一个类创建子类,并在子类中采用方法拦截技术拦截所有父类方法的调用,这时可以顺势织入横切逻辑。
代理对象的伪代码
```java
package com.neuedu.sm.service;
public class UserService {
public void save() {
//方法之前 开启 事务
System.out.println("保存用户数据");
// 提交事务
//回滚实物
}
}
```
## 代理对象
```java
package com.neuedu.sm.service;
public class UserServiceProxy extends UserService {
@Override
public void save() {
System.out.println("开启事务");
super.save();
System.out.println("提交事务");
}
public static void main(String[] args) {
UserService userService = new UserServiceProxy();
userService.save();
}
}
```

可以通过AOP的机制 实现动态代理
### 4.3.1. 切面(Aspect)
切面是切点和通知组成,通知和切点共同定义了切面的全部内容即:它是什么,在何时何处完成其功能;
举例:将pointcut和Advice配置整合的过程切面
### 4.3.2. 连接点(Joinpoint)
连接点是在应用执行过程中能够插入切面的一个点,Spring仅支持方法的连接点,即仅能在方法调用前,方法调用后,方法抛出异常时及方法调用前后插入切面代码。 .
举例:如果在insert之前执行扩展(增强、通知),简单理解insert这个方法可以称之为连接点。
连接点: 1 Com.neuedu.service.StuServiceImpl.insert()
连接点: 2 Com.neuedu.service.UserServiceImpl.insert()
### 4.3.3. 切点(Pointcut)
```
Com.neuedu.service.*Impl.insert()
```
### 4.3.4. 通知(Advice)、增强
切面的工作被成为通知,定义了切面是什么及何时使用。除了描述切面要完成的工作,通知还解决了何时执行这个工作的问题,它应该在某个方法被调用之前?之后?等。
举例:额外定义一个方法想要在连接点上进行扩展的功能
#### 4.3.4.1. Spring切面可以应用5种类型的通知:
前置通知(Before)在目标方法被调用之前调用通知功能;
后置通知(After)在目标方法被完成之后调用通知功能,不关心方法的输出是什么;
环绕通知(Around advice)通知包裹了目标方法,在目标方法调用之前和之后执行自定义的行为;
异常通知(After-throwing)在目标方法抛出异常后调用通知;
返回通知(After-returning)在目标方法成功执行之后调用通知;
### 4.3.5. 目标对象(Target)
通知逻辑的织入目标类。如果没有AOP,那么目标业务类需要自己实现所有的逻辑,在AOP的帮助下,目标类只需要实现那些非横切逻辑的程序逻辑,而比如事务管理等这些横切逻辑就可以使用AOP动态织入特定的连接点上。
举例:两个Service即是目标对象
### 4.3.6. 引入(Introduction)
引介是一种特殊的通知,为类添加一些属性和方法。这样,即使一个业务类原本没有实现某个接口,通过AOP的引介功能,也可以动态地为该业务类添加接口的实现逻辑,使业务类成为这个接口的实现类。
几乎由框架完成,我们可以暂时透明
### 4.3.7. 代理(Proxy)
一个类被AOP织入通知后,就产生一个结果类,它是融合了原类和通知逻辑的代理类。根据不同的代理方式,代理类既可能是和原类具有相同接口的类,也可能就是原类的子类,所以可以采用与调用原类相同的方式调用代理类。
举例:IOC容器创建的两个Service类型对象
### 4.3.8. 织入(Weaving)
织入是将通知添加到目标类的具体连接点上的过程.AOP就像一台织布机,将目标类,通知或引介编织到一起。 AOP有三种织入方式: ①编译期织入:切面在目标类编译时被织入,需要特殊的编译器; ②类装载期织入:切面在目标类加载到JVM时被织入,需要特殊的类装载器; ③动态代理织入:切面在应用运行的某个时刻呗织入,AOP容器会为目标对象动态创建一个代理对象;
## 面相切面编程(AOP) 需要编写的代码
- 目标对象( UserService、RoleService 各种Bean)
- 通知: 在目标对象方法基础上添加的功能(属性、加方法 加代码 )
- 编写切面
- 切点
- 通知
- 使用目标对象--- 从容器中获取-- 由容器调用AOP (织入) 代理对象
# AOP案例
定义 UseService、RoleService 包含 save功能,
> 需求 需要给 save功能 执行之前 添加一个开启事务的功能
- 创建项目 spring-07-aop-xml
- 添加依赖 spirng-context(core、bean、express、context)、spirng-aop 、aspectjweaver
- 编写 UseService、RoleService
子项目中需要的依赖
```xml
4.0.0
com.neuedu.sm
spring-learn
1.0
spring-07-aop-xml
jar
spring-07-aop-xml
http://maven.apache.org
UTF-8
org.springframework
spring-context
${spring.version}
org.springframework
spring-aop
org.aspectj
aspectjweaver
org.springframework
spring-test
test
org.junit.jupiter
junit-jupiter-api
${junit.version}
test
```
## 编写AOP基础环境代码
- UseService、RoleService @Service
- 配置文件 spring-aop 使用包扫描 component-scan
```xml
```
编写单元测试 获取UserService、RoleService测试save功能
```java
package com.neuedu.sm;
import com.neuedu.sm.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
@SpringJUnitConfig(locations = "classpath:spring-aop.xml")
public class UserServiceTest {
@Autowired
UserService userService;
@Test
public void test() {
userService.save();
}
}
```
测试结果

## 配置AOP(代完成)
**前置通知(Before)在目标方法被调用之前调用通知功能;**
后置通知(After)在目标方法被完成之后调用通知功能,不关心方法的输出是什么;
环绕通知(Around advice)通知包裹了目标方法,在目标方法调用之前和之后执行自定义的行为;
异常通知(After-throwing)在目标方法抛出异常后调用通知;
返回通知(After-returning)在目标方法成功执行之后调用通知
### 编写通知方法(Before)
在容器中注册Bean(通知类)
````java
package com.neuedu.sm.service.advice;
import org.springframework.stereotype.Component;
@Component
public class MyAdvice {
public void before() {
System.out.println("在service方法之前执行");
System.out.println("在service方法之前执行");
System.out.println("在service方法之前执行");
System.out.println("在service方法之前执行");
}
}
````
## 配置切面(使用XML)
```xml
```
### 测试代码
```java
package com.neuedu.sm;
import com.neuedu.sm.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
@SpringJUnitConfig(locations = "classpath:spring-aop.xml")
public class UserServiceTest {
@Autowired
UserService userService;
@Test
public void test() {
userService.save();
}
}
```

## 其他通知类型
基础的Bean代码
```java
package com.neuedu.sm.service;
import org.springframework.stereotype.Service;
@Service
public class RoleService {
public void save() {
System.out.println("RoleService.save --保存[角色 ]");
}
public void queryList() {
System.out.println("RoleService.queryList --查询角色");
}
public void update(boolean success) throws Exception {
System.out.println("RoleService.update --更新角色");
if (!success) {
throw new Exception("产生错误了");
}
}
public Object getById(boolean success) throws Exception {
System.out.println("RoleService.queryById --查询对象");
if (!success) {
throw new Exception("产生错误了");
}
return "查询对象-Role ";
}
}
```
```java
package com.neuedu.sm.service;
import org.springframework.stereotype.Service;
@Service
public class UserService {
public void save() {
System.out.println("UserService.save --保存用户");
}
public void queryList() {
System.out.println("UserService.queryList --查询用户");
}
/**
* 可能产生异常的方法
* @param success
* @throws Exception
*/
public void update(boolean success) throws Exception {
System.out.println("UserService.update --更新用户");
if (!success) {
throw new Exception("产生错误了");
}
}
public Object getById(boolean success) throws Exception {
System.out.println("UserService.queryById --查询对象");
if (!success) {
throw new Exception("产生错误了");
}
return "查询对象-User ";
}
}
```
### 配置通知
```xml
```
### 测试代码
```java
package com.neuedu.sm;
import com.neuedu.sm.service.RoleService;
import com.neuedu.sm.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
@SpringJUnitConfig(locations = "classpath:spring-aop.xml")
public class RoleServiceTest {
@Autowired
RoleService roleService;
@Test
public void test() {
roleService.save();
}
@Test
public void testQuery() {
roleService.queryList();
}
@Test
public void testUpdate() throws Exception {
// boolean success = true;
boolean success = false;
roleService.update(success);
}
@Test
public void testQueryById() throws Exception {
// boolean success = true;
boolean success = false;
roleService.getById(success);
}
}
```
## 使用xml注解扫描+AOP注解
将spring-07-aop-xml 复制一份 spring-08-aop-xml-annotation
将xml中 aop:config标签的配置 换成注解
### 使用配置类
```java
package com.neuedu.sm.service.advice;
import org.aopalliance.intercept.Joinpoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyAdvice {
/**
*
* 使用XML的形式注册切点
*
*
*
*
*/
@Pointcut("execution(* com.neuedu.sm.service.*.save(..) )")
public void serviceSave() {
}
@Pointcut("execution(* com.neuedu.spring.service.*.query*(..) )")
public void serviceQuery() {
}
@Pointcut("execution(* com.neuedu.spring.service.*.update*(..) )")
public void serviceUpdate() {
}
@Pointcut("execution(* com.neuedu.spring.service.*.getById(..))")
public void serviceGetById() {
}
/**
* 前置通知 @Before("serviceSave()")
*
*/
@Before("serviceSave()")
public void before() {
System.out.println("1在service方法之前执行");
System.out.println("1在service方法之前执行");
System.out.println("1在service方法之前执行");
}
/**
* 前置通知 @After("serviceSave()")
*
*/
@After("serviceSave()")
public void afterAdvice() {
System.out.println("2在service方法之后执行");
System.out.println("2在service方法之后执行");
System.out.println("2在service方法之后执行");
}
/**
* 环绕通知 @Around("serviceQuery()")
*
* @param pjp
*/
@Around("serviceQuery()")
public void around(ProceedingJoinPoint pjp) {
// 执行方法
System.out.println("环绕通知 1 ");
try {
Object target = pjp.getTarget();
System.out.println("target = " + target);
Object[] args = pjp.getArgs();
Signature signature = pjp.getSignature();
System.out.println("signature = " + signature);
Object aThis = pjp.getThis();
//System.out.println("aThis = " + aThis);
pjp.proceed(); //原始目标的方法
//提交事务
} catch (Throwable e) {
//回滚事务
throw new RuntimeException(e);
}
System.out.println("环绕通知 2 ");
}
/**
* 异常通知 @AfterThrowing(pointcut = "serviceUpdate()",throwing = "ex")
*
* @param ex
*/
@AfterThrowing(pointcut = "serviceUpdate()", throwing = "ex")
public void cathException(Exception ex) {
System.out.println("异常通知 " + ex.getMessage());
System.out.println("把异常写入到数据库中。。。。");
}
/**
* 返回后通知 @AfterReturning("serviceGetById()")
*
*/
@AfterReturning("serviceGetById()")
public void returnAdvice() {
System.out.println("返回之后执行");
}
}
```

## 使用Java配置类管理AOP
新建项目spring-09-aop-javaconfig
### 配置类
```java
package com.neuedu.sm;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
* ComponentScan 默认扫描 当前配置所在的包 和子包
*/
@Configuration
//@ComponentScan("com.neuedu.sm")
@ComponentScan()
@EnableAspectJAutoProxy
public class App {
}
```
### 测试类
````java
package com.neuedu.sm;
import com.neuedu.sm.service.RoleService;
import com.neuedu.sm.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
@SpringJUnitConfig(classes = App.class)
public class RoleServiceTest {
@Autowired
RoleService roleService;
@Test
public void test() {
roleService.save();
}
@Test
public void testQuery() {
roleService.queryList();
}
@Test
public void testUpdate() throws Exception {
// boolean success = true;
boolean success = false;
roleService.update(success);
}
@Test
public void testQueryById() throws Exception {
//boolean success = true;
boolean success = false;
roleService.getById(success);
}
}
````
```java
package com.neuedu.sm;
import com.neuedu.sm.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
@SpringJUnitConfig(classes = App.class)
public class UserServiceTest {
@Autowired
UserService userService;
@Test
public void test() {
userService.save();
}
@Test
public void testQuery() {
userService.queryList();
}
}
```
# 代理模式
实现动态代理有两种形式:
1. jdk动态代理:根据目标类接口获取代理类实现规则,生成代理对象。这个代理对象,也是目标类接口的一个实现类。
2. cglib动态代理:根据目标类本身获取代理类实现规则,生成代理对象。这个代理对象,也是目标类的一个子类。 (如果目标类为final,则不能使用CGLib实现动态代理)
SpringAOP可以自动在jdk动态代理和CGLib动态代理之间进行切换,规则如下:
1. 如果目标对象实现了接口,采用jdk动态代理实现aop。
2. 如果目标对象没有实现接口,采用CGLib动态代理实现aop。
3. 如果目标对象实现了接口,但仍然想要使用CGLIB实现aop,可以手动进行配置。


# 整合MyBatis
整合的思路 将SQLSessionFactory、Mapper(dao)由 Spring的IOC工厂托管,需要用的时候 @Autowired 自动从容器中获取。
- spring(xml+包扫描注册Bean)+MyBatis (mybaits-spring.jar : 写好了 创建SQLSessionFactory的代码)
- spring(配置类)+MyBatis (mybaits-spring.jar : 写好了 创建SQLSessionFactory的代码)
## 基于xml的Spirng整合MyBatis
- 创建spring的ioc项目
- 添加依赖
- spring-context 、Spring-aop 、aspectjweaver 、spring-test、
- spring-jdbc、
- junit、 Mybaits、
- MYSQL驱动 、druidDatasource 、
- mybatis-spring 整合的包
- 创建一个配置文件spring-mybaits.xml
- 编写一个Bean @Service UserService 类
- 测试
- 从容器中获取 Userservice
- 添加 MyBaits
- 编写 SQLMapConfig.xml
- 基于数据库生成PO、Mapper.xml、Mapper.java
- 在IOC容器中配置SQLSessionFactory、
- 将Mapper的创建过程 `session.getMapper(XXXXMapper.class); 交给Spring IOC
- 测试
- 从IOC容器中拿到Mapper并测试
## spring-10-spring-xml-mybaits-configxml
### 1 添加依赖
```xml
4.0.0
com.neuedu.spring
spring-learn
1.0
spring-10-spring-xml-mybaits-configxml
jar
spring-10-spring-xml-mybaits-configxml
http://maven.apache.org
UTF-8
org.springframework
spring-context
${spring.version}
org.springframework
spring-aop
org.springframework
spring-test
org.springframework
spring-jdbc
org.aspectj
aspectjweaver
org.junit.jupiter
junit-jupiter-api
${junit.version}
com.mysql
mysql-connector-j
com.alibaba
druid
org.mybatis
mybatis
org.mybatis
mybatis-spring
org.projectlombok
lombok
```
### 2 ioc的配置文件
spring-mybatis.xml
基础包 : **com.neuedu.sm**
- po
- mapper
- service
- controller
```xml
```
### 3 编写测试的Bean(Userservice)
```java
package com.neuedu.sm.service;
import org.springframework.stereotype.Service;
@Service
public class UserService{
public void list(){
System.out.println("UserService.list--Service层");
}
}
```
### 4 使用单元测试 获取Bean 测试IOC
```java
package com.neuedu.sm.service;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.junit.jupiter.api.Assertions.*;
@SpringJUnitConfig(locations = "classpath:spring-mybatis.xml")
class UserServiceTest {
@Autowired
private UserService userService;
@Test
void list() {
userService.list();
}
}
```

### 5 添加Mybaits的配置文件
#### SQLMapconfig.xml
```xml
```
#### jdbc.properties
```properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/assica?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root
```
### 6 生成po、mapper
DBMS: MySQL (ver. 8.0.30)
Case sensitivity: plain=lower, delimited=lower
Driver: MySQL Connector/J (ver. mysql-connector-j-8.2.0 (Revision: 06a1f724497fd81c6a659131fda822c9e5085b6c), JDBC4.2)
Ping: 61 ms
SSL: yes


\


### 7 让容器管理SQLSessionFactory Mapper
- mybatis-spring
父项目 家版本号,子项目直接依赖(不需要版本号)
```xml
org.mybatis
mybatis-spring
4.0.0
compile
```
##### 在IOC配置文件中注册 SqlSessionFactory 、数据源
```xml
```
##### 测试SqlSessionFactory
```java
package com.neuedu.sm.service;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
@SpringJUnitConfig(locations = "classpath:spring-mybatis.xml")
public class SqlSessionFactoryTest {
@Autowired
private SqlSessionFactory sqlSessionFactory;
@Test
public void testSqlSessionFactory() {
System.out.println(sqlSessionFactory);
}
}
```
#### 使用MapperBean 在 容器中注册 Mapper的的代理对象

```xml
```
```java
package com.neuedu.sm.mapper;
import com.neuedu.sm.po.Users;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.junit.jupiter.api.Assertions.*;
@SpringJUnitConfig(locations = "classpath:spring-mybatis.xml")
class UsersMapperTest {
@Autowired
private UsersMapper usersMapper;
@Test
void selectByPrimaryKey() {
long id = 1L;
Users users = usersMapper.selectByPrimaryKey(id);
System.out.println("users = " + users);
}
}
```
#### 使用 spring 加载 jdbc.properties属性文件
```xml
```

### 批量注册Mapper到IOC工厂
- 使用MapperScannerConfigurer 批量注册Mapper到IOC
- 给sessionFactory 注入配置项,代替SqlMapConfig配置文件
```xml
```
## 使用事务
编写了一个需要事务的方法(常见的方式 是在 service层上添加事务 查询(select) 、更新(update、insert、delete) )
```java
package com.neuedu.sm.service;
import com.neuedu.sm.mapper.UsersMapper;
import com.neuedu.sm.po.Users;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService{
@Autowired
private UsersMapper usersMapper;
/**
* 保存的功能
* @param
* @return
*/
public boolean update(boolean error){
Users user1 = usersMapper.selectByPrimaryKey(1L);
Users user2 = usersMapper.selectByPrimaryKey(2L);
user1.setEmail("+100");
int insert = usersMapper.updateByPrimaryKey(user1);
if(error){
throw new RuntimeException("过程出错了");
}
user2.setEmail("-100");
insert += usersMapper.updateByPrimaryKey(user2);
return insert + insert == 2 ;
}
public void list(){
System.out.println("UserService.list--Service层");
}
}
```
```java
package com.neuedu.sm.service;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.junit.jupiter.api.Assertions.*;
@SpringJUnitConfig(locations = "classpath:spring-mybatis.xml")
class UserServiceTest {
@Autowired
private UserService userService;
@Test
void list() {
userService.list();
}
@Test
void update() {
boolean error = true;
boolean success = userService.update(error);
System.out.println("success = " + success);
}
}
```
当boolean error的值为true的时候 出现一个 第一个账户 有“+100” 标记,但是第二个账户因为代码报错而没有执行

### 使用spirng-tx中支持的事务管理器 配置aop切面,实现事务的功能
- 配置事务管理(相当于是通知)TxManager(DataSourceTransactionManager)
- 给事务管理器配置切面
- 在什么方法上添加通知(开启事务、提交事务 )
在spring-mybaits.xml中添加事务配置
```xml
```

再次测试发现 UserService的 update功能室有事务的
事务的传播特性
**注解中的 propagation 属性,可以设置事务传播行为。属性值为:**
1. **REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,就加入到这个事务中。这是最常见的选择。**
2. **SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。**
3. **MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常。**
4. **REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。**
5. **NOT_SUPPORTED:以非事务方式执行操作,如果存在事务,就把当前事务挂起。**
6. **NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。**
事务的隔离特性
1️⃣ Read uncommitted (读未提交):最低级别,任何情况都无法保证。
第一隔离级别怕回滚,因为它能读取到别的事务未提交的数据。如果当前事务将这个数据当成真正的数据,那么如果别的事务回滚,那么就会数据错误,导致脏读。
2️⃣ Read committed (读已提交):可避免脏读的发生。
第二个隔离级别怕提交,因为提交会导致不可重复读。
3️⃣ Repeatable read (可重复读):可避免脏读、不可重复读的发生。*MySQL默认隔离级别
4️⃣ Serializable (串行化):可避免脏读、不可重复读、幻读的发生
———————————————
为啥Oracle默认隔离级别是Read committer
为啥MySQL默认隔离级别是Repeatable read
### 使用Transactional注解替代 切面的xml配置
详见 spring-13-spring-xml-mybaits-tx-annotation 项目 在 12的基础上,修改 Service添加注解,并将spring配置文件中的切面配置去掉, 添加注解驱动
```java
package com.neuedu.sm.service;
import com.neuedu.sm.mapper.UsersMapper;
import com.neuedu.sm.po.Users;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService{
@Autowired
private UsersMapper usersMapper;
/**
* 保存的功能
* @param
* @return
*/
@Transactional(propagation = Propagation.REQUIRED,isolation= Isolation.DEFAULT,rollbackFor = Exception.class)
public boolean update(boolean error) throws Exception {
Users user1 = usersMapper.selectByPrimaryKey(1L);
Users user2 = usersMapper.selectByPrimaryKey(2L);
user1.setEmail("+100");
int insert = usersMapper.updateByPrimaryKey(user1);
if(error){
throw new Exception("过程出错了");
}
user2.setEmail("-100");
insert += usersMapper.updateByPrimaryKey(user2);
return insert + insert == 2 ;
}
public void list(){
System.out.println("UserService.list--Service层");
}
}
```
```xml
```
## 使用配置类替代spring的配置文件
参考
spring-14-spring-mybaits-javaconfig-all
Java配置类
```java
package com.neuedu.sm;
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@Configuration
//扫描包 注册组件
@ComponentScan
//启动事务
@EnableTransactionManagement
public class SpringApp {
/**
* 配置数据源
* @return
*/
@Bean
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://localhost:3306/assica?characterEncoding=utf-8");
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
/**
* 配置SQLSessionFactory
* @param dataSource
* @return
* @throws Exception
*/
//@Bean("sqlSessionFactory")
@Bean
public SqlSessionFactory sqlSessionFactory( DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setLogImpl(StdOutImpl.class);
sqlSessionFactoryBean.setConfiguration(configuration);
return sqlSessionFactoryBean.getObject();
}
//注册Mapper
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setBasePackage("com.neuedu.sm.mapper");
//mapperScannerConfigurer.setSqlSessionTemplateBeanName("sqlSessionFactory");
mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
return mapperScannerConfigurer;
}
//注册事务管理器到IOC容器
@Bean
public TransactionManager txManager( DataSource dataSource){
TransactionManager txmanager = new DataSourceTransactionManager(dataSource);
return txmanager;
}
}
```
测试类
```java
package com.neuedu.sm.service;
import com.neuedu.sm.SpringApp;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.junit.jupiter.api.Assertions.*;
@SpringJUnitConfig(classes = SpringApp.class)
class UserServiceTest {
@Autowired
private UserService userService;
@Test
void list() {
userService.list();
}
@Test
void update() throws Exception {
//boolean error = true;
boolean error = false;
boolean success = userService.update(error);
System.out.println("success = " + success);
}
}
```
可以发现事务生效了
### 使用@MapperScan注解
在Spring配置类中我们声明了 MapperScannerConfigurer 用于注册 Mapper 到IOC容器中,
- 可以通过在XXXMapper接口上添加@Mapper 实现单个Mapper的注册
- 可以在配置类上添加@MapperScan("com.neuedu.sm.mapper") 用于替代 MapperScannerConfigurer 实现批量注册
- 最终的配置类如下:(后面使用的SpirngBoot就是类似如下的写法)
```java
package com.neuedu.sm;
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@Configuration
//扫描包 注册组件
@ComponentScan
//启动事务
@EnableTransactionManagement
//相当于 MapperScannerConfigurer 的功能, 自动注册Mapper接口代理对象到IOC容器
@MapperScan("com.neuedu.sm.mapper")
public class SpringApp {
/**
* 配置数据源
* @return
*/
@Bean
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://localhost:3306/assica?characterEncoding=utf-8");
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
/**
* 配置SQLSessionFactory
* @param dataSource
* @return
* @throws Exception
*/
//@Bean("sqlSessionFactory")
@Bean
public SqlSessionFactory sqlSessionFactory( DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setLogImpl(StdOutImpl.class);
sqlSessionFactoryBean.setConfiguration(configuration);
return sqlSessionFactoryBean.getObject();
}
/**
*
* 注册Mapper
* @return
*/
//@Bean
//public MapperScannerConfigurer mapperScannerConfigurer(){
// MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
// mapperScannerConfigurer.setBasePackage("com.neuedu.sm.mapper");
// // 错误的 : mapperScannerConfigurer.setSqlSessionTemplateBeanName("sqlSessionFactory");
// mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
// return mapperScannerConfigurer;
//}
//注册事务管理器到IOC容器
@Bean
public TransactionManager txManager( DataSource dataSource){
TransactionManager txmanager = new DataSourceTransactionManager(dataSource);
return txmanager;
}
}
```