全文大纲
- 1、Spring
- 1.1、简介
- 1.2、优点
- 1.3、组成(七大模块)
- 1.4、拓展
- 2、IOC理论推导
- 2.1、最初的开发
- 2.2、改进后的开发
- 2.3、总结
- 3、Hello Spring
- 3.1、测试案例一
- 3.2、测试案例二
- 3.3、补充
- 4、IOC创建对象的方式
- 4.1、默认采用的是无参构造
- 4.2、通过构造器创建
- 5、Spring配置
- 5.1、别名
- 5.2、Bean配置
- 5.3、import
- 6、依赖注入
- 6.1、构造器注入
- 6.2、set方式注入
- 6.3、其他方式注入
- 6.4、Bean的作用域
- 7、Bean的自动装配
- 7.1、ByName自动装配
- 7.2、ByType自动装配
- 7.3、使用注解实现自动装配
- 8、使用注解开发
- 9、使用Java的方式配置Sping
- 10、代理模式
- 11、AOP
- 11.1、什么是AOP
- 11.2、AOP在Spring中的作用
- 11.3、使用Spring实现AOP
- 1、方式一:使用原生Spring API接口
- 2、方式二:使用自定义的类进行切面定义
- 3、方式三:使用注解实现
- 12、整合Mybatis
- 12.1、编写一个mybatis测试
- 12.2、Mybatis-Spring整合方式一
- 12.3、Mybatis-Spring整合方式二
- 13、声明式事务
- 13.1、事务
- 13.2、spring中的事务
- 13.3、利用AOP实现声明式事务案例(含所有代码)
1、Spring
1.1、简介
- 2002年,首次出了Spring框架的雏形:interface21框架
- Spring框架即以interface21框架为基础,经过重新设计,并且不断丰富其内涵,于2004年3月24日,发布了1.0正式版
- Rod Johnson,Spring Framework创始人,悉尼大学博士
- spring理念:使现有技术更加容易使用,本身是一个大杂烩,整合现有的技术框架
- SSH:Struct2 + Spring + Hibernate
- SSM:SpringMVC + Spring + Mybatis
官网:https://spring.io/projects/spring-framework
官方下载地址:http://repo.spring.io/release/org/springframework/spring
GitHub:https://github.com/spring-projects/spring-framework
maven依赖:
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
1.2、优点
- Spring是一个开源的免费的框架(容器)
- Spring是一个轻量级的、非侵入式的框架
- 控制反转(IOC)、面向切面编程(AOP)
- 支持事务的处理,对框架整合的支持
Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架
1.3、组成(七大模块)
1.4、拓展
现代化的java开发,就是基于Spring的开发
- SpringBoot
- 一个快速开发的脚手架
- 基于SpringBoot可以快速的开发单个微服务
- 约定大于配置
- SpringCloud
- SpringCloud是基于SpringBoot实现的
弊端:发展太久之后,违背了原来的理念,配置十分繁琐,人称配置地狱。
2、IOC理论推导
- UserDao接口
- UserDaoImol实现类
- UserService业务接口
- UserServiceImpl业务实现类
2.1、最初的开发
UserDao
package pers.mobian;
public interface UserDao {
public void getUser();
}
UserDaoImpl
package pers.mobian;
public class UserDaoImpl implements UserDao {
@Override
public void getUser() {
System.out.println("获取到对应的用户");
}
}
UserService
package pers.mobian;
public interface UserService {
public void getUser();
}
UserServiceImpl
package pers.mobian;
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
@Override
public void getUser() {
userDao.getUser();
}
}
测试类
package pers.mobian;
public class test01 {
public static void main(String[] args) {
UserDaoImpl userDao = new UserDaoImpl();
userDao.getUser();
}
}
总结:传统的开发方式,对于每新添加一个功能,就需要去原代码中进行修改,不符合面向对象的开闭原则。所以需要改进。
2.2、改进后的开发
修改后的UserServiceImpl
package pers.mobian;
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void getUser() {
userDao.getUser();
}
}
之前程序是主动创建对象,控制权在程序员手上,使用set注入之后,程序员不再具有主动性,而是变成了被动接收
修改后的测试类
package pers.mobian;
public class test01 {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
((UserServiceImpl)userService).setUserDao(new UserDaoImpl());
userService.getUser();
}
}
此时,如果需要添加新的功能,那么要做的只是在测试类中对不同的对象进行实例化。继而出现了权力反转,不需要修改原有代码,即可完成新功能的使用。这种思想,从本质上解决了程序员再去创建对象的问题。系统的耦合性大大降低,程序员可以更加专注在自己的业务实现上,这也是IOC的原型。
2.3、总结
IOC本质
控制反转IOC(Inversion of Control),是一种设计塑像,DI(Dependency Injection)是实现IOC的一种方式。没有IOC的程序中,我们使用面向对象编程,对象的创建和对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,可以这么理解,所谓的控制反转就是获得以来对象的方式反转了。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的心事定义在实现类中,从而达到零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的就是IOC容器,其实现方法就是依赖注入。
3、Hello Spring
3.1、测试案例一
- 新建一个pojo类
package pers.mobian.pojo;
public class Hello {
private String str;
@Override
public String toString() {
return "Hello{" +
"str='" + str + '\'' +
'}';
}
//如果删除此方法,程序会运行出错
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
}
- 新建一个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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--使用Spring来创建我们的对象,在Spring中,这些都成为Bean
类型 变量名 = new 类型();
Hello hello = new Hello();
id = 变量名
class = new 的对象
property 相当于给对象中的属性设置一个值
-->
<bean id="hello" class="pers.mobian.pojo.Hello">
<property name="str" value="Hello Spring"></property>
</bean>
</beans>
- 新建一个测试类
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pers.mobian.pojo.Hello;
public class test01 {
public static void main(String[] args) {
//获取Spring的上下文对象
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//我们的对象现在都在Sping中管理了,我们要使用,直接去容器里面取出来即可
Hello hello = (Hello) context.getBean("hello");
Hello hello1 = (Hello) context.getBean("hello");
System.out.println(hello==hello1);
System.out.println(hello.toString());
}
}
总结:
这个过程就叫控制反转
控制: 谁控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象由Spring来创建
反转: 程序本身不创建对象,而是变成被动接收对象
依赖注入: 就是利用set方法来进行注入的
IOC是一种编程思想,由主动的编程变成被动的接收。对象由Spring来创建、管理、装配
3.2、测试案例二
在2.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userDaoImpl" class="pers.mobian.UserDaoImpl"></bean>
<bean id="userServiceImpl" class="pers.mobian.UserServiceImpl">
<!--
ref:引用Spring创建的对象
value:传递的是具体的值
-->
<property name="userDao" ref="userDaoImpl"></property>
</bean>
</beans>
- 测试类
package pers.mobian;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class test01 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("userServiceImpl");
userServiceImpl.getUser();
}
}
总结:往后,每次需要修改只需要修改beans.xml文件即可,大大提高了效率。
3.3、补充
ClassPathXmlApplicationContext —> ApplicationContext类的层级关系
4、IOC创建对象的方式
4.1、默认采用的是无参构造
<bean id="user" class="pers.mobian.ioc.User">
</bean>
4.2、通过构造器创建
- 使用index创建
<bean id="user" class="pers.mobian.ioc.User">
<!--index的值是对象的有参构造的参数顺序-->
<constructor-arg index="0" value="默辨"></constructor-arg>
<constructor-arg index="1" value="22"></constructor-arg>
</bean>
- 使用type创建
<bean id="user" class="pers.mobian.ioc.User">
<!--type的对应类型为对象的具体类型-->
<constructor-arg type="int" value="22"></constructor-arg>
<constructor-arg type="java.lang.String" value="默辨"></constructor-arg>
</bean>
- 使用name创建
<bean id="user" class="pers.mobian.ioc.User">
<!--name属性对应的值为具体的参数名字-->
<constructor-arg name="age" value="22"></constructor-arg>
<constructor-arg name="name" value="默辨"></constructor-arg>
</bean>
输出结果均为
这里是有参构造
默辨
User{name='默辨', age=22}
注意:
在配置文件加载异构,就会得到所有的容器对象,然后测试类中需要那个就调用哪个。
5、Spring配置
5.1、别名
<alias name="user" alias="user3"></alias>
//两句等效
User user = (User) context.getBean("user3");
User user = (User) context.getBean("user3");
5.2、Bean配置
<!--
id:bean的唯一标识符,也就是相当于我们的对象
class:bean对象所对应的权限定名:包名+路径
name:即别名,且name可以取多个别名,且分割形式很多:,;还有空格
-->
<bean id="user" class="pers.mobian.ioc.User" name="user2 user3;user4,user5">
</bean>
5.3、import
将多人开发的配置文件进行整合,使用的时候就使用总的就行
<import resource="beans1.xml"></import>
<import resource="beans2.xml"></import>
<import resource="beans3.xml"></import>
6、依赖注入
6.1、构造器注入
前面已有
6.2、set方式注入
pojo类:
package pers.mobian.pojo;
public class Address {
private String address;
public Address() {
}
public Address(String address) {
this.address = address;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Address{" +
"address='" + address + '\'' +
'}';
}
}
package pers.mobian.di;
import pers.mobian.pojo.Address;
import java.util.*;
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String, String> card;
private Set<String> game;
private String wife;
private Properties info;
public Student() {
}
public Student(String name, Address address, String[] books, List<String> hobbys, Map<String, String> card, Set<String> game, String wife, Properties info) {
this.name = name;
this.address = address;
this.books = books;
this.hobbys = hobbys;
this.card = card;
this.game = game;
this.wife = wife;
this.info = info;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String[] getBooks() {
return books;
}
public void setBooks(String[] books) {
this.books = books;
}
public List<String> getHobbys() {
return hobbys;
}
public void setHobbys(List<String> hobbys) {
this.hobbys = hobbys;
}
public Map<String, String> getCard() {
return card;
}
public void setCard(Map<String, String> card) {
this.card = card;
}
public Set<String> getGame() {
return game;
}
public void setGame(Set<String> game) {
this.game = game;
}
public String getWife() {
return wife;
}
public void setWife(String wife) {
this.wife = wife;
}
public Properties getInfo() {
return info;
}
public void setInfo(Properties info) {
this.info = info;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", address=" + address +
", books=" + Arrays.toString(books) +
", hobbys=" + hobbys +
", card=" + card +
", game=" + game +
", wife='" + wife + '\'' +
", info=" + info +
'}';
}
}
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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--注册Bean-->
<bean id="address" class="pers.mobian.pojo.Address">
<property name="address" value="重庆"></property>
</bean>
<bean id="student" class="pers.mobian.di.Student">
<!--1、普通注入-->
<property name="name" value="默辨"></property>
<!--2、Bean对象注入-->
<property name="address" ref="address"></property>
<!--3、数组注入-->
<property name="books">
<array>
<value>《人间失格》</value>
<value>《活着》</value>
<value>《浪潮之巅》</value>
</array>
</property>
<!--4、list集合注入-->
<property name="hobbys">
<list>
<value>跑步</value>
<value>打游戏</value>
</list>
</property>
<!--5、map集合注入-->
<property name="card">
<map>
<entry key="IDCard" value="1234567890"></entry>
<entry key="BankCar" value="987654321"></entry>
</map>
</property>
<!--6、set集合注入-->
<property name="game">
<set>
<value>LOL</value>
<value>CF</value>
</set>
</property>
<!--7、null值注入-->
<property name="wife">
<null></null>
</property>
<!--8、property注入-->
<property name="info">
<props>
<prop key="administrator">[email protected]</prop>
<prop key="support">[email protected]</prop>
<prop key="development">[email protected]</prop>
</props>
</property>
</bean>
</beans>
6.3、其他方式注入
c命名空间(构造器注入)注入和p命名空间注入(set注入)
<!--约束-->
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
代码示例:
<bean id="people1" class="pers.mobian.pojo.People" p:age="22" p:name="mobian"></bean>
<bean id="people2" class="pers.mobian.pojo.People" c:age="22" c:name="默辨"></bean>
<bean id="people3" class="pers.mobian.pojo.People" c:_0="mobian" c:_1="11"></bean>
测试代码:
ApplicationContext context = new ClassPathXmlApplicationContext("beans1.xml");
People people1 = context.getBean("people1", People.class);
System.out.println(people1.toString());
People people2 = context.getBean("people2", People.class);
System.out.println(people2.toString());
6.4、Bean的作用域
- 单例模式(Spring默认机制)
<bean id="people1" class="pers.mobian.pojo.People" p:age="22" p:name="mobian" scope="singleton"></bean>
- 原型模式
<bean id="people1" class="pers.mobian.pojo.People" p:age="22" p:name="mobian" scope="prototype"></bean>
- 其余的request、session、application只在web开发中使用
7、Bean的自动装配
- 自动装配式Spring满足bean依赖的一种方式
- Spring会在上下文中自动寻找,并自动给bean装配属性
在Spring中有三种装配属性
- 在XML中显式装配
- 在java中显式装配
- 隐式的自动装配bean(重要)
7.1、ByName自动装配
<bean id="dog" class="pers.mobian.pojo.Dog"></bean>
<bean id="cat" class="pers.mobian.pojo.Cat"></bean>
<bean id="cat1" class="pers.mobian.pojo.Cat"></bean>
<!--byName:会自动在容器的上下文中查找,和自己对象set方法后面的值对应的beanid-->
<bean id="people" class="pers.mobian.pojo.People" autowire="byName">
</bean>
7.2、ByType自动装配
<bean id="dog" class="pers.mobian.pojo.Dog"></bean>
<bean id="cat1" class="pers.mobian.pojo.Cat"></bean>
<!--byType:会在容器的上下文中查找,和自己对象属性类型相同的bean-->
<bean id="people" class="pers.mobian.pojo.People" autowire="byType">
</bean>
总结:
- 使用byName的时候,需要保证所有的bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致
- 使用byType的时候,需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性的类型一致
7.3、使用注解实现自动装配
jdk1.5开始支持注解,Spring2.5开始支持注解
The introduction of annotation-based configuration raised the question of whether this approach is “better” than 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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
1@Autowired(默认为true)
@Autowired(required = false)
public @interface Autowired {
boolean required() default true;
}
直接在属性上使用即可,也可以在set方式上使用,查找方式是通过ByName实现
使用Autowired我们可以不用编写set方法,前提式你这个自动装配的属性在IOC容器中存在,且符合名字的byName
@Autowired(required = false)
private Cat cat;
@Autowired(required = false)
private Dog dog;
@Nullable
使用此注解以后,可以在使用构造器注入的时候,使其为null
public People(@Nullable Cat cat, @Nullable Dog dog) {
this.cat = cat;
this.dog = dog;
}
@Qualifier
该注解,可以指定对应的需要装配的bean
<bean id="dog22" class="pers.mobian.pojo.Dog"></bean>
<bean id="dog1" class="pers.mobian.pojo.Dog"></bean>
<bean id="cat1" class="pers.mobian.pojo.Cat"></bean>
<bean id="cat22" class="pers.mobian.pojo.Cat"></bean>
<bean id="people" class="pers.mobian.pojo.People"></bean>
//由于此时没有id为cat和dog,不用Qualifier指定就会报错
@Autowired
@Qualifier(value = "cat1")
private Cat cat;
@Autowired
@Qualifier(value = "dog1")
private Dog dog;
总结:
@Autowired和@Qualifier(value = “XXX”)为一套配合使用的注解。可以用于指定唯一的bean对象
@Resource
此注解为java自带的注解
@Resource(name = "cat11")
小结:
@Resource和@Autowired的区别:
- 都是用来自动装配的,都可以放在属性字段上面
- @Autowired通过bytype的方式实现,而且必须要求这个对象存在(常用)
- @Resource默认通过byname的方式实现,如果找不到就通过bytype实现,如果两个都找不到的情况下就会报错
- 执行顺序:@Autowired通过bytype的方式实现。@Resource默认通过byname的方式实现
8、使用注解开发
在Spring4.0以后,使用注解开发,需要导入aop的jar包
- 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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--使用此注解可以扫描指定路径下的类,将其设置为可用注解实现功能-->
<context:component-scan base-package="pers.mobian.pojo"/>
<context:annotation-config/>
</beans>
package pers.mobian.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//该注解等价于<bean id="user" class="pers.mobian.pojo.User"/>
@Component
public class User {
//该注解等价于 <property name="name" value="mobian"></property>
@Value("mobain")
private String name;
public String getName() {
return name;
}
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pers.mobian.pojo.User;
public class test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = context.getBean("user", User.class);
System.out.println(user.getName());
}
}
- 衍生的注解
@Component的衍生注解,在web开发过程中,会按照MVC三层架构分层
- dao(@Repository)
- service(@Service)
- controller(@Controller)
这四个注解功能都是一样的,都是将代码,某个类注册到Spring中,装配Bean
- 自动装配
- @Autowired
- @Qualifier
- @Resource
- 作用域
@Scope
@Component
@Scope("singleton")
public class User {
@Value("mobain")
private String name;
public String getName() {
return name;
}
}
- 小结
xml与注解:
- xml功能更强大,,维护简单
- 注解使用方便,维护比较复杂
xml与注解的最佳实践:
- xml用来管理bean
- 注解只负责完成属性的注入
使用注解开发的时候,不要忘记了开启注解的支持以及添加约束
9、使用Java的方式配置Sping
测试代码:
- 新建一个pojo类
package pers.mobian.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class User {
//注入值
@Value("mobian")
private String name;
public User(String name) {
this.name = name;
}
public User() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
- 新建一个java的配置类
package per.mobian.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import pers.mobian.pojo.User;
//这个也会被Spring容器托管,注册到容器中,因为他本身也是一个@Component的封装
//@Configuration代表这是一个配置类,就类似于我们之前的beans.xml
@Configuration
//配置类可以通过该方式去扫描类
@ComponentScan("pers.mobian.pojo")
//引入其他的配置类
@Import(ConfigTest01.class)
public class ConfigTest {
//注册一个Bean,就类似于我们之前的写的一个bean标签
//该方法的名字,就相当于bean标签的id属性
//该方法的返回值,就相当于bean标签的class属性
@Bean
public User getUser(){
return new User();//返回要注入到bean的对象
}
}
- 新建一个测试类
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import per.mobian.config.ConfigTest;
import pers.mobian.pojo.User;
public class test {
public static void main(String[] args) {
//如果完全使用了配置类方法去做,我们就只能通过AnnotationConfigApplicationContext上下文来获取容器,通过配置类的class对象加载
ApplicationContext context = new AnnotationConfigApplicationContext(ConfigTest.class);
User user = (User) context.getBean("getUser");
System.out.println(user.getName());
}
}
测试结果:
mobian
这种纯java的配置方式,在SpringBoot中随处可见
10、代理模式
代理模式
11、AOP
11.1、什么是AOP
AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
11.2、AOP在Spring中的作用
提供声明式事务;允许用户自定义切面
- 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 …
- 切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类。
- 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
- 目标(Target):被通知对象。
- 代理(Proxy):向目标对象应用通知之后创建的对象。
- 切入点(PointCut):切面通知 执行的 “地点”的定义。
- 连接点(JointPoint):与切入点匹配的执行点。
SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:
通知类型 | 连接点 | 实现接口 |
前置通知 | 方法前 | org.springframework.aop.MethodBeforeAdvice; |
后置通知 | 方法后 | org.springframework.aop.AfterReturningAdvice; |
环绕通知 | 方法前后 | org.aopalliance.intercept.MethodInterceptor; |
异常抛出通知 | 方法抛出异常 | org.springframework.aop.ThrowsAdvice; |
引介通知 | 类中增加新的方法属性 | org.springframework.aop.IntroductionInterceptor; |
即 AOP 在不改变原有代码的情况下 , 去增加新的功能
11.3、使用Spring实现AOP
使用AOP织入,需要导入一个依赖包!
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
需要导入相关的约束
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
execution 表达式
execution(* pers.mobian.aop.UserServiceImpl.*(…))
execution()是常用的切点函数,其语法如下所示:
- execution(): 表达式主体。
- 第一个*号:表示返回类型, *号表示所有的类型。
- 包名:表示需要拦截的包名,此处为指定的pers.mobian.aop.UserServiceImpl路径的包
- 第二个*号:表示方法,*表示所有的方法。
- *(…):括弧里面表示方法的参数,两个句点表示任何参数
1、方式一:使用原生Spring API接口
测试代码:
- 接口类:UserService
package pers.mobian.aop;
public interface UserService {
public void add();
public void delete();
public void update();
public void select();
}
- 接口的实现类
package pers.mobian.aop;
public class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("我是增加的方法");
}
@Override
public void delete() {
System.out.println("我是删除的方法");
}
@Override
public void update() {
System.out.println("我是修改的方法");
}
@Override
public void select() {
System.out.println("我是查找的方法");
}
}
- 新增的两个日志类
package pers.mobian.aop;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class Log implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(method.getName()+"方法执行了");
}
}
package pers.mobian.aop;
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("我是结尾的方法");
}
}
- bean.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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--注入bean-->
<bean id="log" class="pers.mobian.aop.Log"></bean>
<bean id="userServiceImpl" class="pers.mobian.aop.UserServiceImpl"></bean>
<bean id="afterLog" class="pers.mobian.aop.AfterLog"></bean>
<!--方式一:使用原生Spring API接口-->
<!--配置aop:需要导入aop的约束-->
<aop:config>
<!--切入点 expression:表达式 execution(要执行的位置 全路径名.*(..))-->
<aop:pointcut id="pointcut" expression="execution(* pers.mobian.aop.UserServiceImpl.*(..))"></aop:pointcut>
<!--执行环绕增强-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"></aop:advisor>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"></aop:advisor>
</aop:config>
</beans>
- 测试类
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pers.mobian.aop.UserService;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//动态代理的是接口,所以应该使用接口来接收
UserService userService = (UserService) context.getBean("userServiceImpl");
userService.add();
userService.delete();
userService.update();
userService.select();
}
}
- 测试结果
add方法执行了
我是增加的方法
我是结尾的方法
delete方法执行了
我是删除的方法
我是结尾的方法
update方法执行了
我是修改的方法
我是结尾的方法
select方法执行了
我是查找的方法
我是结尾的方法
2、方式二:使用自定义的类进行切面定义
- 自定义日志类
package pers.mobian.aop;
public class DiyLog {
public void after(){
System.out.println("方法执行后");
}
public void before(){
System.out.println("方法执行前");
}
}
- 修改bean.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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--注入bean-->
<bean id="userServiceImpl" class="pers.mobian.aop.UserServiceImpl"></bean>
<bean id="diyLog" class="pers.mobian.aop.DiyLog"></bean>
<!--方法二:自定义类-->
<aop:config>
<!--自定义切面, ref要引用的类-->
<aop:aspect ref="diyLog">
<!--切入点-->
<aop:pointcut id="pointcut" expression="execution(* pers.mobian.aop.UserServiceImpl.*(..))"></aop:pointcut>
<!--通知-->
<aop:before method="before" pointcut-ref="pointcut"></aop:before>
<aop:after method="after" pointcut-ref="pointcut"></aop:after>
</aop:aspect>
</aop:config>
</beans>
- 测试类
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pers.mobian.aop.UserService;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//动态代理的是接口,所以应该使用接口来接收
UserService userService = (UserService) context.getBean("userServiceImpl");
userService.add();
}
}
- 执行结果
方法执行前
我是增加的方法
方法执行后
3、方式三:使用注解实现
- 自定义切面注解类
package pers.mobian.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class AnnotationPointcut {
@Before("execution(* pers.mobian.aop.UserServiceImpl.*(..))")
public void before() {
System.out.println("方法执行前");
}
@After("execution(* pers.mobian.aop.UserServiceImpl.*(..))")
public void after() {
System.out.println("方法执行后");
}
//在环绕增强中,我们可以给顶一个参数,代表我们要获取处理切入的点
@Around("execution(* pers.mobian.aop.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint jp) throws Throwable {
System.out.println("环绕前");
Object proceed = jp.proceed();//执行方法
System.out.println("环绕后");
// Signature signature = jp.getSignature();//获取方法的签名
// System.out.println(signature);
}
}
- 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"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<!--方式三:使用注解定义-->
<!--注入bean-->
<bean id="userServiceImpl" class="pers.mobian.aop.UserServiceImpl"></bean>
<bean id="annotationPointcut" class="pers.mobian.aop.AnnotationPointcut"></bean>
<!--开启注解支持
JDK(默认使用 proxy-target-class="false")
cglib(proxy-target-class="true")
-->
<aop:aspectj-autoproxy proxy-target-class="false" ></aop:aspectj-autoproxy>
</beans>
- 测试类
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pers.mobian.aop.UserService;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//动态代理的是接口,所以应该使用接口来接收
UserService userService = (UserService) context.getBean("userServiceImpl");
userService.add();
}
}
- 执行结果
//需要记住方法的执行顺序
环绕前
方法执行前
我是增加的方法
环绕后
方法执行后
12、整合Mybatis
步骤:
- 导入相关的jar包
- junit
- mybatis
- mysql数据库
- spring相关的
- aop织入包
- mybatis-spring(新增)
对应的maven依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
- 编写配置文件
- 测试
12.1、编写一个mybatis测试
官方学习网址:https://mybatis.org/spring/zh/index.html
虽然随时可能会崩,进不去呀。
- 编写实体类
- 编写核心配置文件
- 编写接口
- 编写Mapper.xml
- 测试
12.2、Mybatis-Spring整合方式一
在mybatis测试成功的前提下,进行整合
注意选择的版本。
MyBatis-Spring | MyBatis | Spring 框架 | Spring Batch | Java |
2.0 | 3.5+ | 5.0+ | 4.0+ | Java 8+ |
1.3 | 3.4+ | 3.2.2+ | 2.1+ | Java 6+ |
测试案例:
- 将mybatis-config.xml配置文件中的部分信息进行转移到新建的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:aop="http://www.springframework.org/schema/aop" xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<!--
1、获取数据源:dataSource
2、获取对应的sqlSessionFactory:将数据源(dataSource)注入SqlSessionFactoryBean中即可
3、获取sqlSession:利用sqlSessionFactory得到SqlSessionTemplate,但我们习惯将SqlSessionTemplate变成sqlSession
4、获取userMapper的Bean对象:此处需要新建一个Mapper的实现类,才能完成此操作
-->
<!--1、DataSource:使用Spring提供的数据源代替Mybatis原来的配置 c3p0 dbcp druid
此处使用Spring提供的JDBC:org.springframework.jdbc.datasource
相当于environments中的信息被替换了
-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC"></property>
<property name="username" value="root"></property>
<property name="password" value=""></property>
</bean>
<!--2、得到sqlSessionFactory
相当于对应的mappers被替换了
-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<!--绑定Mybatis的配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<property name="mapperLocations" value="classpath:pers/mobian/dao/*.xml"></property>
</bean>
<!--3、得到SqlSessionTemplate:就是得到我们使用的sqlSession-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!--只能使用构造器注入sqlSessionFactory,因为他没有set方法-->
<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
</bean>
<!--4、获取Bean对象-->
<bean id="userMapper" class="pers.mobian.dao.UserMapperImpl">
<property name="sqlSession" ref="sqlSession"></property>
</bean>
</beans>
- mybatis-config.xml剩余信息
<?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>
<!--可以留下两项:设置和别名管理
当然Spring也可以替换
-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<typeAliases>
<typeAlias type="pers.mobian.pojo.User" alias="user"></typeAlias>
</typeAliases>
<!--被Spring代替了-->
<!--<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&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC"/>-->
<!--<property name="username" value="root"/>-->
<!--<property name="password" value=""/>-->
<!--</dataSource>-->
<!--</environment>-->
<!--</environments>-->
<!--被Spring代替了-->
<!--<mappers>-->
<!--<mapper resource="pers/mobian/dao/UserMapper.xml"/>-->
<!--</mappers>-->
</configuration>
- UserMapper.xml文件不需要修改
- 新建的UserMapper的实现类,即UserMapperImpl类
package pers.mobian.dao;
import org.mybatis.spring.SqlSessionTemplate;
import pers.mobian.pojo.User;
import java.util.List;
public class UserMapperImpl implements UserMapper {
//我们所有的操作,都是用sqlSession来执行,现在都是使用SqlSessionTemplate
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
@Override
//将测试类中的步骤转移到了实现类中进行
public List<User> selectUser() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.selectUser();
}
}
- 测试
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pers.mobian.dao.UserMapper;
import pers.mobian.pojo.User;
import java.util.List;
public class MyTest {
@Test
public void selectUser(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
List<User> userList = userMapper.selectUser();
for (User user : userList) {
System.out.println(user);
}
}
}
- 执行结果
12.3、Mybatis-Spring整合方式二
利用继承SqlSessionDaoSupport类的方式
//SqlSessionDaoSupport类的源码。如果传入的参数为null,则可以自己创建
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
if (this.sqlSessionTemplate == null || sqlSessionFactory != this.sqlSessionTemplate.getSqlSessionFactory()) {
this.sqlSessionTemplate = createSqlSessionTemplate(sqlSessionFactory);
}
}
修改后的测试案例:
- 新建的UserMapper的实现类,并且继承SqlSessionDaoSupport类,即UserMapperImpl2类
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper {
//此方式不需要像第一种方式那样,set一个变量。
@Override
public List<User> selectUser() {
// SqlSession sqlSession = getSqlSession();
// UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// List<User> userList = mapper.selectUser();
// return userList;
//官方建议直接使用一句话编写,并返回。
return getSqlSession().getMapper(UserMapper.class).selectUser();
}
}
- 在spring-dao.xml类种配置Bean对象
<!--3、得到SqlSessionTemplate:就是得到我们使用的sqlSession-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!--只能使用构造器注入sqlSessionFactory,因为他没有set方法-->
<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
</bean>
<!--4、获取Bean对象-->
<bean id="userMapper" class="pers.mobian.dao.UserMapperImpl">
<property name="sqlSession" ref="sqlSession"></property>
</bean>
<!--可以将配置的Bean对象,单独放置在applicationContext.xml种-->
<!--新方式直接将3和4合并为一步-->
<bean id="userMapper2" class="pers.mobian.dao.UserMapperImpl2">
<!--传递的参数直接变成了第三步的sqlSessionFactory-->
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>
- 测试
@Test
public void selectUser(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
UserMapper userMapper = context.getBean("userMapper2", UserMapper.class);
List<User> userList = userMapper.selectUser();
for (User user : userList) {
System.out.println(user);
}
}
13、声明式事务
13.1、事务
- 把一组业务当成一个业务来做,要么都成功,要么都失败
- 事务在项目开发中十分重要,涉及到数据的一致性问题,不能马虎
- 确保完整性和一致性
事务ACID原则
- 原子性
- 一致性
- 隔离性:多个事务可能同时操作同一个资源,防止数据损坏
- 持久性:事务一旦提交,无论系统发生什么问题,结果都不会被影响,持久化的写到了存储器中
13.2、spring中的事务
- 声明式事务:AOP
- 编程式事务:在代码中进行事务的管理
声明式事务测试案例
- 引入约束
xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
- 配置事务声明及事务通知
<!--配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--结合AOP实现事务的织入-->
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给那些方法配置事务-->
<!--配置事务的传播特性:new propagation(propagation的默认属性为REQUIRED)-->
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="select" read-only="true"/>
</tx:attributes>
</tx:advice>
- 配置切入点
<!--配置事务切入-->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* pers.mobian.mapper.*.*(..))"></aop:pointcut>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"></aop:advisor>
</aop:config>
13.3、利用AOP实现声明式事务案例(含所有代码)
- 添加对应的maven依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
- 新建实体类User
package pers.mobian.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String pwd;
}
- 新建一个Mapper接口
package pers.mobian.mapper;
import pers.mobian.pojo.User;
import java.util.List;
public interface UserMapper {
//查询所有的用户信息
List<User> selectUser();
//添加用户
int insertUser(User user);
//根据id删除用户
int deleteUser(int id);
}
- 新建一个Mapper对应的xml文件
<?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="pers.mobian.mapper.UserMapper">
<select id="selectUser" resultType="user">
select * from mybatis.user
</select>
<insert id="insertUser" parameterType="user">
insert into mybatis.user (id, name, pwd) values (#{id},#{name},#{pwd})
</insert>
<delete id="deleteUser">
delete from mybatis.user where id=#{id}
</delete>
</mapper>
- 新建Mapper类的实现类
package pers.mobian.mapper;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import pers.mobian.pojo.User;
import java.util.List;
public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper {
@Override
public List<User> selectUser() {
UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
mapper.insertUser(new User(77, "七七", "77777"));
mapper.deleteUser(2);
return mapper.selectUser();
}
@Override
public int insertUser(User user) {
return getSqlSession().getMapper(UserMapper.class).insertUser(user);
}
@Override
public int deleteUser(int id) {
return getSqlSession().getMapper(UserMapper.class).deleteUser(id);
}
}
- 新建mybatis的配置文件
<?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>
<!--可以留下两项:设置和别名管理
当然Spring也可以替换
-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<typeAliases>
<typeAlias type="pers.mobian.pojo.User" alias="user"></typeAlias>
</typeAliases>
</configuration>
- 新建spring-dao配置文件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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd ">
<!--
1、获取数据源:dataSource
2、获取对应的sqlSessionFactory:将数据源(dataSource)注入SqlSessionFactoryBean中即可
3、获取sqlSession:利用sqlSessionFactory得到SqlSessionTemplate,但我们习惯将SqlSessionTemplate变成sqlSession
4、获取userMapper的Bean对象:此处需要新建一个Mapper的实现类,才能完成此操作
-->
<!--1、DataSource:使用Spring提供的数据源代替Mybatis原来的配置 c3p0 dbcp druid
此处使用Spring提供的JDBC:org.springframework.jdbc.datasource
相当于environments中的信息被替换了
-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC"></property>
<property name="username" value="root"></property>
<property name="password" value=""></property>
</bean>
<!--2、得到sqlSessionFactory
相当于对应的mappers被替换了
-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<!--绑定Mybatis的配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<property name="mapperLocations" value="classpath:pers/mobian/mapper/UserMapper.xml"></property>
</bean>
<!--配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--结合AOP实现事务的织入-->
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给那些方法配置事务-->
<!--配置事务的传播特性:new propagation(propagation的默认属性为REQUIRED)-->
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="select" read-only="true"/>
</tx:attributes>
</tx:advice>
<!--配置事务切入-->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* pers.mobian.mapper.*.*(..))"></aop:pointcut>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"></aop:advisor>
</aop:config>
</beans>
- 新建spring的配置文件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"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<import resource="spring-dao.xml"></import>
<bean id="userMapper" class="pers.mobian.mapper.UserMapperImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>
<bean id="user" class="pers.mobian.pojo.User"></bean>
</beans>
- 测试
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pers.mobian.mapper.UserMapper;
import pers.mobian.pojo.User;
import java.util.List;
public class MyTest {
@Test
public void selectUser(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper selectUser = context.getBean("userMapper", UserMapper.class);
List<User> userList = selectUser.selectUser();
for (User user : userList) {
System.out.println(user);
}
}
}
- 目录结构
- 执行结果