• 【Spring】Spring学习笔记完整篇


    文章目录

    Spring

    官网 Spring | Home

    spring-framework 弹簧框架 (spring.io)

    官方文档:[Index of /spring-framework/docs

    核心技术 (spring.io)


    下载的spring web mvc:

    <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-jdbcartifactId>
        <version>5.2.0.RELEASEversion>
    dependency>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    1、简介

    1. 2002,首次推出spring框架雏形,interface21框架!

    2. 2004年3月24日,spring 1.0版本发布

    3. Rod Johnson , spring Framework 创始人

    4. spring理念:让现有技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架!

    • SSH Strut2+spring+Hibernate
    • SSM SpringMVC+Spring+Mybatis

    官网:Spring Framework

    官方下载地址:Index of /spring-framework/docs

    github:https://github.com/spring-projects/spring-framework

    优点

    • 开源、免费的框架(容器)
    • 轻量级
    • 非入侵式(导入spring框架后不会改变项目原来的结构内容)
    • 控制反转IOC,面向切面编程AOP
    • 支持事务处理
    • 支持框架整合

    Spring 就是一个轻量级的控制反转IOC和面向切面编程AOP的框架!

    组成

    Spring框架由组织成约20个模块的功能组成。这些模块分为核心容器、数据访问/集成、Web、AOP(面向方面的编程)、检测、消息传递和测试,如下图所示。

    image-20220802084037659

    • springboot
      • 一个快速开发的脚手架
      • 基于springboot可以快速的开发单个微服务
      • 约定大于配置
    • spring cloud
      • spring cloud 是基于springboot实现的

    弊端

    发展了太久,违背了原来的理念:配置十分繁琐!

    2、IOC 控制反转

    总结: IOC就是将对象由Spring去创建,管理,装配!

    之前开发:

    1. UserDao接口
    2. UserDaoImpl实现类
    3. UserService业务接口
    4. UserServiceImpl业务实现类

    弊端:

    用户更改需求的时候,程序员需要改动具体实现接口的代码,很麻烦!

    利用生成 Set 接口,发生了革命性变化!

    public class UserServiceImpl implements UserService{
    
        //利用set进行动态实现Dao层接口的注入
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
    
        //利用新new出来的Dao层implement实现类对象,调用Dao层接口方法
        //private UserDao userDao = new UserDaoImpl();
        private UserDao userDao = new UserDaoOracleImpl();
    
        public void getUser() {
    
            //userDao.getUser();
            //userDao.getMySql();
            userDao.getOracle();
        }
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 之前,主动创建对象,控制权在程序员手上

    • 现在,使用 Set 注入后,程序员没有了主动性,变成了被动接受的对象,那么控制权交给了谁?

    • 程序员不用再管理对象的创建

    • 系统耦合性大大降低

    • 程序员可以更加专注在业务上

    控制什么?

    控制创建对象的方式;

    谁来控制?

    原本应用程序的对象是通过程序本身控制创建,

    加入Spring后,对象由Spring来创建;

    反转?

    程序本身不再创建对象了,而是被动接收Spring创建的对象;

    依赖注入DI?

    就是利用set方法进行注入;

    IOC和DI关系

    DI(依赖注入)是实现IOC(控制反转)这个编程思想的一种方式;

    IOC本质

    • IOC控制反转 inversion of control
    • IOC是一种编程思想,由主动编程变成被动的接收对象
    • 通过 newClassPathXMLApplicationContext去浏览底层代码
    • IOC是Spring框架的核心内容
    • IOC是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。

    image-20220802142638472

    3、hello spring

    Hello.java

    package com.kuang.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 + '\'' +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    beans.xml

    
    <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="hello" class="com.kuang.pojo.Hello">
            <property name="str" value="Spring">property>
        bean>
    
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    MyTest.java

    import com.kuang.pojo.Hello;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MyTest {
    
        public static void main(String[] args) {
    
            // 1、获取Spring的上下文对象,拿到Spring容器
            // 允许容器从各种外部资源(如本地文件系统、Java 等)加载配置元数据。ApplicationContext CLASSPATH
            ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
            
            // 2、容器在手,天下我有,需要什么,直接从容器中获取
            // 我们的对象现在都在Spring中管理了,我们要使用对象,不用new,直接从ApplicationContext里面取出来就行
            Hello hello = (Hello) context.getBean("hello");
            System.out.println(hello.toString());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    测试结果:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qWHpZJth-1660011316857)(https://s2.loli.net/2022/08/02/93S5JK1R78M6Fyf.png)]

    ApplicationContext和ServletContext相同处

    【JSP】JSP从基础到入门笔记完整一篇_宋丹敏的博客-CSDN博客

    ServletContext

    image-20220802143439557

    ApplicationContext

    用对象的时候去容器中拿

    image-20220802143943516

    Hello对象由谁创建?

    是由Spring容器创建的;

    
    <bean id="hello" class="com.kuang.pojo.Hello">
        <property name="str" value="Spring">property>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    Hello对象属性如何设置?

    由Spring容器设置;

    <bean id="hello" class="com.kuang.pojo.Hello">
        
        
        
        <property name="str" value="Spring">property>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    ClassPathXmlApplicationContext生成路径

    ClassPathXmlApplicationContext生成

    4、IOC创建对象的方式

    4.1 使用无参构造创建

    User.java

    package com.kuang.pojo;
    
    public class User {
    
        private String name;
    
        // 无参构造
        public User(){
            System.out.println("user的无参构造");
        }
    
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void show(){
            System.out.println("name="+name);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    beans.xml

    
    <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="user" class="com.kuang.pojo.User">
            <property name="name" value="秦疆">property>
        bean>
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    MyTest.java

    import com.kuang.pojo.User;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MyTest {
    
        public static void main(String[] args) {
    
            //获取应用上下文,加载beans.xml配置元数据
            ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
            //通过bean 从context中获取User对象
            User user = (User) context.getBean("user");
    
            user.show();
    
            //System.out.println(user.getName());
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    运行结果:

    image-20220802161632580

    这里如果将User实体类中定义的无参构造删除,只写入有参构造方法,就会报错:

    image-20220802162140521

    所以得出结论:IOC创建对象通过使用无参构造创建

    那么只有有参构造时候,如何创建对象?

    4.2 使用有参构造创建

    第一种:下标赋值

    bean.xml

    <bean id="user" class="com.kuang.pojo.User">
        
        <constructor-arg index="0" value="狂神说Java">constructor-arg>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    实例:

    User.java

    package com.kuang.pojo;
    
    public class User {
    
        private String name;
    
        // 有参构造
        public User(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void show(){
            System.out.println("name="+name);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    bean.xml

    
    <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="user" class="com.kuang.pojo.User">
            <constructor-arg index="0" value="狂神说Java">constructor-arg>
        bean>
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    MyTest.java

    import com.kuang.pojo.User;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MyTest {
    
        public static void main(String[] args) {
    
            //获取应用上下文,加载beans.xml配置元数据
            ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
            //通过bean 从context中获取User对象
            User user = (User) context.getBean("user");
    
            user.show();
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    测试结果:

    image-20220802163100397

    第二种:类型匹配【不建议】

    bean.xml

    <bean id="user" class="com.kuang.pojo.User">
        <constructor-arg type="java.lang.String" value="秦疆">constructor-arg>
    bean>
    
    • 1
    • 2
    • 3

    第三种:参数名【推荐】

    
    <bean id="user" class="com.kuang.pojo.User">
        <constructor-arg name="name" value="qingjiang">constructor-arg>
    bean>
    
    • 1
    • 2
    • 3
    • 4

    总结

    Spring容器, 就类似于婚介所,不管你要不要,婚介所都有已经存在的对象,如果对象你想要,直接获取就行,而婚介所中存在的每个对象都独一无二

    在配置文件加载的时候,容器中的管理对象就已经初始化了!

    5、Spring配置说明

    5.1 别名alias

    bean.xml

        
        <bean id="user" class="com.kuang.pojo.User">
            <constructor-arg name="name" value="qingjiang">constructor-arg>
        bean>
    
        
        <alias name="user" alias="userNew">alias>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    5.2 Bean的配置

    
    <bean id="userT" class="com.kuang.pojo.UserT" name="user2 u2, u3, u4" >
        <property name="name" value="西部开源">property>
    bean>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    5.3 import导入

    这个import,一般用于团队开发;

    可以将多个配置文件,导入合并为一个;

    applicationContext.xml

    
    <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">
    
        <import resource="beans.xml">import>
        <import resource="beans2.xml">import>
        <import resource="beans3.xml">import>
    
    
    
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    image-20220802172234995

    • 项目多人开发,多个人复制不同的类开发,不同的类需要注册不同的bean中,我们就可以利用import将所有人的beans.xml合并成一个总的!

    6、DI依赖注入

    6.1 构造器注入

    看4.1 4.2

    Spring团队提倡构造函数注入

    6.2 set注入【重点】

    • 依赖注入:Set注入!
      • 依赖:bean对象的创建依赖于容器!
      • 注入:bean对象中的所有属性,由容器来注入!

    【环境搭建】

    Student.java

    package com.kuang.pojo;
    
    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> games;
        private String wife; //妻子,空指针null
        private Properties 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> getGames() {
            return games;
        }
    
        public void setGames(Set<String> games) {
            this.games = games;
        }
    
        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 +
                    ", games=" + games +
                    ", wife='" + wife + '\'' +
                    ", info=" + info +
                    '}';
        }
    }
    
    
    • 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
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94

    applicationContext.xml

    
    <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="address" class="com.kuang.pojo.Address">
            <property name="address" value="西安">property>
        bean>
    
        <bean id="student" class="com.kuang.pojo.Student">
    
            
            <property name="name" value="秦疆">property>
    
            
            <property name="address" ref="address">property>
    
            
            <property name="books">
                <array>
                    <value>红楼梦value>
                    <value>西游记value>
                    <value>三国演义value>
                array>
            property>
    
            
            <property name="hobbys">
                <list>
                    <value>听歌value>
                    <value>敲代码value>
                    <value>看书value>
                list>
            property>
    
            
            <property name="card">
                <map>
                    <entry  key="身份证" value="123712739171293">entry>
                    <entry  key="银行卡" value="234234234324344">entry>
                map>
            property>
    
            
            <property name="games">
                <set>
                    <value>LOLvalue>
                    <value>cfvalue>
                    <value>红警value>
                    <value>吃鸡value>
                set>
            property>
    
            
            <property name="wife">
                <null>null>
            property>
    
            
            <property name="info">
                <props>
                    <prop key="driver">231231prop>
                    <prop key="url">nanprop>
                    <prop key="username">rootprop>
                    <prop key="password">231231prop>
                props>
            property>
        bean>
    
    beans>
    
    • 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
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    测试类:

    import com.kuang.pojo.Student;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MyTest {
    
        public static void main(String[] args) {
    
            //引入applicationContext.xml配置文件,生成ApplicationContext,要获取对象的时候,只需要从context中获取就行
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
            //拿到student的对象 == 拿到student的bean
            Student student = (Student) applicationContext.getBean("student");
    
            //输出student对象中name属性的value值
            System.out.println(student.toString());
    
    
            /*
                Student{
                    name='秦疆',
                    address=Address{address='西安'},
                    books=[红楼梦, 西游记, 三国演义],
                    hobbys=[听歌, 敲代码, 看书],
                    card={
                            身份证=123712739171293,
                            银行卡=234234234324344
                    },
                    games=[LOL, cf, 红警, 吃鸡],
                    wife='null',
                    info={
                        password=231231,
                        url=nan,
                        driver=231231,
                        username=root
                    }
                }
    
    
             */
    
        }
    }
    
    
    • 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

    测试结果:获取到了student对象的所有类型注入的值

    image-20220803095506233

    6.3 拓展方式

    image-20220803103220607

    具有p命名空间的xml快捷方式注入

    userBean.xml

    xmlns:p="http://www.springframework.org/schema/p"   
    
    • 1

    具有c命名空间的xml快捷方式注入

    userBean.xml

    xmlns:c="http://www.springframework.org/schema/c"
    
    • 1

    User.java

    package com.kuang.pojo;
    
    public class User {
    
        private String name;
        private int age;
    
        public User(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public User() {
    
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    
    • 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

    userBean.xml

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:c="http://www.springframework.org/schema/c"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        
        <bean id="user" class="com.kuang.pojo.User" p:name="秦疆" p:age="18">bean>
    
        
        <bean id="user2" class="com.kuang.pojo.User" c:age="18" c:name="狂神">bean>
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    测试类:

        @Test
        public void test2(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("userBean.xml");
            User user = (User) applicationContext.getBean("user",User.class);
            User user2 = (User) applicationContext.getBean("user2",User.class);
    
            System.out.println(user.toString());
            //User{name='秦疆', age=18}
    
            System.out.println(user2.toString());
            //User{name='秦疆', age=18}
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    注意

    p命名和c命名空间不能直接使用,需要导入xml头部约束!

    6.4 Bean的作用域

    image-20220803103516999

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B7LpyXuk-1660011316868)(https://s2.loli.net/2022/08/03/ogaMd528nmURvYl.png)]

    1 单例模式【spring默认机制】singleton

    scope="singleton"
    
    • 1

    image-20220803110844621

    userBean.xml

    
        <bean id="user2" class="com.kuang.pojo.User" c:age="18" c:name="狂神" scope="singleton">bean>
    
    • 1
    • 2

    测试类:

        @Test
        public void test2(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("userBean.xml");
            User user = (User) applicationContext.getBean("user",User.class);
            User user2 = (User) applicationContext.getBean("user",User.class);
    
            System.out.println(user.toString());
            //User{name='秦疆', age=18}
    
            System.out.println(user2.toString());
            //User{name='秦疆', age=18}
    
            /*
            hashcode()方法是干什么的?
                hashcode()方法主要配合基于散列的集合一起使用,比如HashSet、HashMap、HashTable。
                当集合需要添加新的对象时,先调用这个对象的hashcode()方法,得到对应的hashcode值,
                实际上hashmap中会有一个table保存已经存进去的对象的hashcode值,
                如果table中没有改hashcode值,则直接存入,
                如果有,就调用equals方法与新元素进行比较,相同就不存了,不同就存入。
             */
            System.out.println(user.hashCode());
            System.out.println(user2.hashCode());
            System.out.println(user == user2);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    测试结果:true

    单例模式,从bean中拿到的对象是同一个

    image-20220803110332137

    2 原型模式 prototype

     scope="prototype"
    
    • 1

    image-20220803111231965

    userBean.xml

        
        <bean id="user2" class="com.kuang.pojo.User" c:age="18" c:name="狂神" scope="prototype">bean>
    
    • 1
    • 2

    测试类: 同上

    测试结果: false

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

    测试类:

        @Test
        public void test2(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("userBean.xml");
            User user = (User) applicationContext.getBean("user",User.class);
            User user2 = (User) applicationContext.getBean("user2",User.class);
    
            System.out.println(user.toString());
            System.out.println(user2.toString());
    
            System.out.println(user.hashCode());
            System.out.println(user2.hashCode());
            System.out.println(user == user2);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    测试结果: false

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

    image-20220803105954271

    3 其余的 request、session、application

    这些只能在web开发中使用到!

    7、Bean的自动装配

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

    在Spring中有三种装配方式:

    1. 在xml中显示的配置
    2. 在java中显示的配置
    3. 隐式的自动装配bean【重要】

    7.1 测试

    环境搭建:一个人有两个宠物!

    Cat.java

    package com.kuang.pojo;
    
    public class Cat {
    
        public void shout(){
            System.out.println("miao~");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Dog.java

    package com.kuang.pojo;
    
    public class Dog {
    
        public void shout(){
            System.out.println("wang~");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    People.java

    package com.kuang.pojo;
    
    public class People {
    
        //人有猫、狗、名字
        private Cat cat;
        private Dog dog;
        private String name;
    
        public People() {
        }
    
        public People(Cat cat, Dog dog, String name) {
            this.cat = cat;
            this.dog = dog;
            this.name = name;
        }
    
        public Cat getCat() {
            return cat;
        }
    
        public void setCat(Cat cat) {
            this.cat = cat;
        }
    
        public Dog getDog() {
            return dog;
        }
    
        public void setDog(Dog dog) {
            this.dog = dog;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
    
        @Override
        public String toString() {
            return "People{" +
                    "cat=" + cat +
                    ", dog=" + dog +
                    ", name='" + name + '\'' +
                    '}';
        }
    
    }
    
    
    • 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

    MyTest.java

    import com.kuang.pojo.People;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MyTest {
    
        @Test
        public void test1(){
    
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
            People people = applicationContext.getBean("people", People.class);
            people.getDog().shout();
            people.getCat().shout();
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    测试结果,环境搭建成功:

    image-20220803133532031

    7.2 ByName自动装配

    通过byname,将cat、dog自动装配到people 的bean中

    beans.xml

    
    <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="dog" class="com.kuang.pojo.Dog">bean>
        <bean  id="cat" class="com.kuang.pojo.Cat">bean>
        <bean id="people" class="com.kuang.pojo.People" autowire="byName">
            <property name="name" value="秦疆">property>
        bean>
    
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    测试类结果:

    image-20220803134031615

    7.3 ByType自动装配【默认】

    beans.xml

    
    <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="dog" class="com.kuang.pojo.Dog">bean>
        <bean  id="cat" class="com.kuang.pojo.Cat">bean>
        <bean id="people" class="com.kuang.pojo.People" autowire="byName">
            <property name="name" value="秦疆">property>
        bean>
    
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    小结:

    • byName的时候,需要保证所有的bean的id唯一,并且这个bean需要和自动注入的属性set方法的值一致!
    • byType的时候,需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性的类型一致!

    8、使用注解开发

    注解实现自动装配

    image-20220803135507985

    jdk1.5支持的注解,spring2.5支持注解!

    使用注解须知:

    1. 导入约束:context 约束
    2. 配置注解的支持:
    
    
    
    
        
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    @Autowired【使用这个】

    • 直接在属性上使用!
    • 也可以在set方法上使用!

    使用 Autowired 我们就可以不用再编写set方法了,前提是你这个自动装配的属性在IOC(spring)容器中存在,且符合名字byname!

    • 先找byType,再找byName;
    	@Autowired(required = false)
        private Cat cat;
        @Autowired
        private Dog dog;
    
    • 1
    • 2
    • 3
    • 4

    科普:

    @Nullable  字段标记了这个注解,说明这个字段可以为null;
    
    • 1

    @Resource

    • byName
    @Resource(name = "cat")
    private Cat cat;
    @Resource(name = "dog")
    private Dog dog;
    
    • 1
    • 2
    • 3
    • 4

    区别:

    1. @Autowired 默认 byType 类型查找,当找不到时候,再通过byName

      @Resource 默认byName 类型查找,

    当注入在IOC容器中该类型只有一个时,就通过ByType进行装配;
    当注入在IOC容器存在多个同一类型的对象时,就是根据ByName进行装配;
    
    @Autowired  直接在属性上使用 or 在set方法上使用(使用了@Autowired后可以将set方法删除)
        使用示例:
        @Autowired
        private Dog dog;
        使用@Autowired就可以不用写set方法了
        
    如果现实的定义了Autowired属性为false,说明这个对象可以为null,否则不允许为空 <==> @Nullable
        @Autowired(required = false)
        private Cat cat;
        
        
    @Qualifer + @Autowired <==> @Resource
    
    
    @Nullable  可以为空
        使用示例:
        public People(@Nullable String name) {
            this.name = name;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    @Component

    组件

    User.java

    @Component
    public class User {
    
    
        public String name;
    
        @Value("kuangshen")
        public void setName(String name){
            this.name = name;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    or

    @Component
    public class User {
    
        @Value("kuangshen")
        public String name;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    beans.xml

    
    <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/>
        
        <context:component-scan base-package="com.kuang.pojo">context:component-scan>
    
    
    
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 衍生的注解

      @Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层!

      • dao【@Repository】
      • service【@Service】
      • controller【@Controller】
      • pojo【@Component】

      加上注解,就说明你这个类被spring托管了,

      这四个注解功能都是一样的,都是代表将某个类注册到spring中,装配bean!

    小结:

    xml与注解:

    • xml更加万能,适用于任何场合!维护方便

    • 注解,不是自己类使用不了,维护相对复杂

    • springboot使用注解比较方便,spring使用还是xml比价方便

    • 我们在使用的过程中,只需要注意一个问题,必须要注解生效:

      1. 开启注解标签支持
      2. 扫描指定包下的注解,这个包下的注解就会生效
          
          <context:annotation-config/>
          
          <context:component-scan base-package="com.kuang">context:component-scan>
      
      
      • 1
      • 2
      • 3
      • 4
      • 5

    9、使用Java的方式配置Spring

    我们现在要完全不使用spring的 beans.xml 配置,全权交给Java来做!

    JavaConfig 是 Spring 的一个子项目,在Spring4之后,它称为了一个核心功能!!!!

    User.java

    package com.kuang.pojo;
    
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    // 这里这个注解的意思,就是说明这个类被 Spring接管了,注册到了容器中
    @Component
    public class User {
    
        private String name;
    
        public String getName() {
            return name;
        }
    
        @Value("qinjiang")  //属性注入值
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    
    
    • 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

    KuangConfig.java

    package com.kuang.config;
    
    import com.kuang.pojo.User;
    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 org.springframework.stereotype.Controller;
    
    //这个也会被 Spring 容器托管,注册到容器中,因为他本身就是一个 Component,
    // @Configuration代表这是一个配置类,和我们之前看到的beans.xml是一样的
    @Configuration
    @ComponentScan("com.kuang.pojo") //可以扫描到pojo包下的实体类
    @Import(KuangConfig2.class) //引入,KuangConfig2配置类
    public class KuangConfig {
    
        // 注册一个bean,就相当于我们之前写的一个bean标签
        // 这个方法的名字就相当于bean标签的id属性,
        // 这个方法的返回值,就相当于bean标签中的class属性
        @Bean
        public User getUser(){
            return new User(); //就是返回到要注入到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

    KuangConfig.java

    package com.kuang.config;
    
    
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class KuangConfig2 {
    
        // 将KuangConfig2配置类融合入KuangConfig中去 ————
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    MyTest.java

    import com.kuang.config.KuangConfig;
    import com.kuang.pojo.User;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContextExtensionsKt;
    
    public class MyTest {
    
        public static void main(String[] args) {
    
    
            //如果完全使用了配置类方式去做,我们就只通过AnnotationConfig 上下文来获取容器,通过配置类的class对象加载!
            ApplicationContext applicationContext = new AnnotationConfigApplicationContext(KuangConfig.class);
            User getUser = (User) applicationContext.getBean("getUser");
            System.out.println(getUser.getName());
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    测试结果:

    image-20220804135945818

    10、代理模式

    1. 为什么要学习代理模式?

      因为这就是SpringAOP的底层;

    10.1 静态代理

    什么是静态代理模式?

    ① 就相当于 房东 – 中介 – 我 之间的关系

    image-20220804141342340

    ② 代理模式分为:静态代理 和 动态代理

    角色分析:

    1. 抽象角色:一般会使用接口或者抽象类来解决(租房)
    2. 真实角色:被代理的角色(我,房东)
    3. 代理角色:代理真实角色,代理后,一般会做些附属工作(中介拟定合同,带你看房、收钱 之类的工作)
    4. 客户:访问代理对象的人!

    代码步骤:

    1. 接口

      Rent.java

      package com.kuang.demo1;
      
      /*
          租房 : 接口
      
              房东 和 中介 的目的都是租房
       */
      public interface Rent {
      
          public void rent();
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
    2. 真实角色

      Landlord.java

      package com.kuang.demo1;
      
      /*
          房东
       */
      public class Landlord implements Rent{
      
          //房东说:要出租房子
      
          public void rent() {
              System.out.println("房东:我要出租房子!");
          }
      
      
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
    3. 代理角色

      Proxy.java

      package com.kuang.demo1;
      
      /*
          中介
              可以帮助房东发布租房的消息
              可以帮你签署合同
              可以带你去看房
              可以收中介费
      
       */
      public class Proxy implements Rent{
      
          //中介说:房东要出租房子
      
          private Landlord landlord;
      
          public Proxy(){
      
          }
      
          public Proxy(Landlord landlord) {
              this.landlord = landlord;
          }
      
          public void rent(){
              landlord.rent();
              seeHouse();
              hetong();
              fare();
          }
      
          //看房
          public void seeHouse(){
              System.out.println("中介带你看房");
          }
      
          //签合同
          public void hetong(){
              System.out.println("签租赁合同");
          }
      
          //收中介费
          public void fare(){
              System.out.println("收中介费");
          }
      }
      
      
      • 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
    4. 客户端访问代理角色

      Client.java

      package com.kuang.demo1;
      
      /*
          客户 :我 访问中介的人
       */
      public class Client {
      
          //我找到中介,得到中介说房东要租房的信息
      
          public static void main(String[] args) {
      
              //先要房东存在,且要出租房子
              Landlord landlord = new Landlord();
              //将房东扔给中介
              Proxy proxy = new Proxy(landlord);
              //中介给我房东出租的房子,此外帮,做一个附属操作
              proxy.rent();
      
          }
      
      
      
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24

    Client.java运行结果:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rEMdqMtJ-1660011316876)(C:\Users\16431\AppData\Roaming\Typora\typora-user-images\image-20220804151407378.png)]

    优缺点:

    好处:

    • 可以使正式角色的操作更加纯粹,不用去关注一个公共的业务!
    • 公共也就交给了代理角色!实现了业务分工!
    • 公共业务发生扩展的时候,方便集中管理!

    缺点:

    • 一个真实角色就会产生一个代理模式,代码量会翻倍,开发效率会变低!

    10.2 静态代理加深理解

    要求在业务层加入日志功能:

    业务需求:要求执行增删改查的时候输入日志;

    **普通思路:**给每个增删改查的方法加入日志输出,执行一个,输出一个;但是这样做十分麻烦;

    例如像这样:

    image-20220804154939080

    **代理思想:**做一个代理,对业务层的增删改查进行代理;代理做的事情就是实现日志功能;让dao层和controller层直接接触代理,不接触service层;

    就是AOP思想,面向切面编程;

    image-20220804154446139

    代码示例:spring-08-proxy

    UserService.java 接口

    package com.kuang.demo2;
    
    //Service层接口
    public interface UserService {
    
        //抽象业务一般就写CRUD
    
        public void add();
        public void delete();
        public void update();
        public void query();
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    UserServiceImpl.java 真实角色

    package com.kuang.demo2;
    
    public class UserServiceImpl implements UserService {
    
        public void add() {
            System.out.println("增加了一个用户");
        }
    
        public void delete() {
            System.out.println("删除了一个用户");
        }
    
        public void update() {
            System.out.println("修改了一个用户");
        }
    
        public void query() {
            System.out.println("查询了一个用户");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    LogProxy.java 代理角色

    package com.kuang.demo2;
    
    /*
        日志功能,代理来实现
     */
    public class LogProxy implements UserService{
    
        //要代理UserServiceImpl,得先有UserServiceImpl
        UserServiceImpl userService = new UserServiceImpl();
    
        // 代理本身干的事情是让每个CRUD方法打印出日志;
        private void log(String msg){
            System.out.println("【log】"+msg+"方法执行了");
        }
    
    
        //新的CRUD方法,不仅要有原来的实现方法,也要有新增的日志方法
    
        public void add() {
            log("add");
            userService.add();//原来的实现方法
        }
    
        public void delete() {
            log("delete");
            userService.delete();//原来的实现方法
        }
    
        public void update() {
            log("update");
            userService.update();//原来的实现方法
        }
    
        public void query() {
            log("query");
            userService.query();//原来的实现方法
        }
    }
    
    
    • 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

    Client.java 客户

    package com.kuang.demo2;
    
    public class Client {
    
        public static void main(String[] args) {
    
            //我要执行,得先有代理
            //LogProxy()在UserService层原有的基础上加入了日志功能,重新实现了UserService接口,所以,返回结果还是UserService类型
            UserService userService = new LogProxy();
            userService.add();
            userService.delete();
            userService.update();
            userService.query();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    代理后测试结果:

    image-20220804161437430

    10.3 动态代理

    动态代理实现的三种方法:

    1. jdk实现动态代理—是基于接口的

      InvocationHandler

      Proxy

      在jdk1.8文档中查这两个类,就可以看到里面的方法,进行参考;

    2. cglib实现动态代理—是基于类的

    3. javasist实现动态代理—是基于java字节码的

    • 动态代理和静态代理角色一样

      • 接口
      • 真实角色
      • 代理角色
      • 访问代理的客户
    • 动态代理的代理类是动态生成的,不是我们自己写的!

    • 动态代理分为两大类:基于接口的动态代理、基于类的动态代理

      • 基于接口—JDK动态代理【我们在这里使用】

      • 基于类:cglib

      • java字节码实现:javasist

        Javassist是一个开源的分析、编辑和创建Java字节码的类库

        cglib 、 javasist 能快速改变类的结构,或者动态生成类。

    JDK动态代理-InvocationHandler

    需要了解两个类:Proxy:代理 , InvocationHandler 调用处理

    InvocationHandler 代理调用处理程序类

    invoke:调用

    • public interface InvocationHandler;
      
      • 1

      InvocationHandler是由代理实例的调用处理程序实现的接口

      每个代理实例都有一个关联的调用处理程序。 当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法。

    • Objectinvoke(Object proxy, 方法 method, Object[] args) 处理代理实例上的方法调用并返回结果。

    JDK动态代理实例:

    1. jdk动态代理–基于接口( InvocationHandler、Proxy )的实例:

      spring-08-proxy

      • 抽象角色 租房接口
      • 真实角色 房东
      • 代理角色 中介:代理调用处理器–实现 InvationHandler类
      • 客户角色 我:访问代理的人

      Rent.java

      package com.kuang.demo3;
      
      /*
          租房 : 接口
      
              房东 和 中介 的目的都是租房
       */
      public interface Rent {
      
          public void rent();
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12

      Landlord.java

      package com.kuang.demo3;
      
      /*
          房东
       */
      public class Landlord implements Rent {
      
          //房东说:要出租房子
      
          public void rent() {
              System.out.println("房东:我要出租房子!");
          }
      
      
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

      ProxyInvocationHandler.java

      package com.kuang.demo3;
      
      import com.kuang.demo3.Rent;
      
      import java.lang.reflect.InvocationHandler;
      import java.lang.reflect.Method;
      import java.lang.reflect.Proxy;
      
      /*
          InvocationHandler 调用处理器
              invocation 调用     handler    处理
              是一个接口(是由代理实例的调用处理程序实现的接口)
              只要实现这个接口,就能自动生成代理,并返回代理结果
      
              每个代理实例都有一个关联的调用处理程序。 当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法。
      
              Object invoke(Object proxy, 方法 method, Object[] args)
              处理代理实例上的方法调用并返回结果。
      
              所有已知实现类:
                  CompositeDataInvocationHandler ,
                  EventHandler ,
                  MBeanServerInvocationHandler ,
                  RemoteObjectInvocationHandler
      
              InvocationHandler 在 java.lang.reflect       包中
                          Proxy 在 java.lang.reflect.Proxy 包中
      
              为某个接口创建Foo代理:
              Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class[] { Foo.class },  handler);
      
       */
      
      //等我们会用到这个类,自动生成代理类!
      public class ProxyInvocationHandler implements InvocationHandler {
      
      
          //被代理的接口
          private Rent rent;
      
          public void setRent(Rent rent) {
              this.rent = rent;
          }
      
          //生成得到代理类
          public Object getProxy(){
              return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
          }
      
          //处理代理实例并返回结果
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      
              //代理添加的新功能
              seeHouse();
              fare();
      
              //动态代理的本质,就是使用反射机制实现!
              Object result = method.invoke(rent, args);
              return result;
          }
      
      
      
          private void fare() {
              System.out.println("收中介费!");
          }
      
          private void seeHouse() {
              System.out.println("中介带看房子!");
          }
      
      
      }
      
      
      • 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
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74

      Client.java

      package com.kuang.demo3;
      
      import com.kuang.demo3.Rent;
      
      public class Client {
      
          public static void main(String[] args) {
      
              //真实角色,客户要拿到信息,虽然有代理(中介),但是真实的角色(房东)也得存在
              Landlord landlord =  new Landlord();
              //代理角色 动态代理,没有代理类,不是真实存在的,是动态生成的,现在没有
              ProxyInvocationHandler pih = new ProxyInvocationHandler();
              //通过 proxyInvocationHandler 调用程序处理角色来处理我们要调用的接口对象!
              pih.setRent(landlord);
      
              //生成代理
              Rent proxy = (Rent) pih.getProxy();
      
              proxy.rent();
      
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23

      测试结果:代理成功!

      image-20220805135126259

    JDK动态代理总结模板:

    ProxyInvocationHandler.java

    package com.kuang.demo4;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /*
        JDK动态代理类模板: 代理Object
     */
    
    //等我们会用到这个类,自动生成代理类!
    public class ProxyInvocationHandler implements InvocationHandler {
    
    
        //1、被代理的接口
        private Object target;
    
        public void setTarget(Object target) {
            this.target = target;
        }
    
        //2、生成得到代理类
        public Object getProxy(){
            return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        }
    
        //3、处理代理实例并返回结果
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
            //代理添加的新功能
            log(method.getName());//通过反射得到方法的名字
    
            //动态代理的本质,就是使用反射机制实现!
            Object result = method.invoke(target, args);
            return result;
        }
    
        //新增的功能:打印输入日志
        public void log(String msg){
            System.out.println("【log】执行了"+msg+"方法");
        }
    
    }
    
    
    • 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

    Client.java

    package com.kuang.demo4;
    
    import com.kuang.demo2.UserService;
    import com.kuang.demo2.UserServiceImpl;
    
    public class Client {
    
        public static void main(String[] args) {
    
            //真实角色
            UserServiceImpl userService = new UserServiceImpl();
    
            //代理角色,现在不存在
            ProxyInvocationHandler pih = new ProxyInvocationHandler();
    
            //设置要代理的对象
            pih.setTarget(userService);
    
            //动态生成代理类
            UserService proxy = (UserService) pih.getProxy();
    
            proxy.add();
            proxy.query();
            proxy.delete();
            proxy.update();
        }
    
    }
    
    
    • 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

    UserService.java

    package com.kuang.demo2;
    
    //Service层接口
    public interface UserService {
    
        //抽象业务一般就写CRUD
    
        public void add();
        public void delete();
        public void update();
        public void query();
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    UserServiceImpl.java

    package com.kuang.demo2;
    
    public class UserServiceImpl implements UserService {
    
        public void add() {
            System.out.println("增加了一个用户");
        }
    
        public void delete() {
            System.out.println("删除了一个用户");
        }
    
        public void update() {
            System.out.println("修改了一个用户");
        }
    
        public void query() {
            System.out.println("查询了一个用户");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    测试结果:Client.java运行结果,代理成功!

    spring-08-proxy

    demo2(Service ServiceImpl) and demo4(Client ProxyInvocationHandler)

    image-20220805141341498

    动态代理的好处:

    • 可以使真实角色的操作更加纯粹!不用关注一些公共的业务

    • 公共的业务就交给了代理角色,实现了业务的分工!

    • 公共业务发生扩展的时候,方便集中!

    • 一个动态代理类代理的是一个接口,一般就是对应的一类业务!

    • 一个动态代理类可以代理多个类,只是实现了同一个接口即可!

    静态代理和动态代理区别:

    • 静态代理使用场景:

      要代理的service业务层有接口的时候,使用静态代理,直接将接口重新实现,而重新实现的代理里面包含新的业务功能+原有的业务,而客户(也就是controller层)不再调用原来的service层,而是调用代理的service层;

      静态代理是将代理写死的!

    • 动态代理使用场景:

      没有接口的时候,只有类,这时候要实现代理,就只能使用动态代理,通过类自动生成代理对象;这里面就是反射思想,通过类的class对象创建实例;

    11、AOP 面向切面编程

    11.1 AOP是什么?

    • AOP: Aspect Oriented Programming 面向切面编程

    • 是OOP的一种延伸;

    • AOP框架:Aspects 框架

    • Spring框架把Aspects框架也集成进来,用来实现AOP面向切面编程

    • 面向切面编程实现就是为了让开发人员专注业务逻辑代码,提高开发效率

    • 通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

    • 是函数式编程的一种衍生范型。

    • 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序可用性,提高开发效率

    AOP 面向切面编程作用:

    像类似于事务处理、日志、权限判断这些代码在类中很多方法中都要使用,如果每个方法中都要写这些代码,就很繁琐,所以把这些都提取为一个工具类,哪个方法要用它,就在哪里方法中注入就行,这样也更好维护。

    POP、OOP、AOP 是什么意思?区别是什么?_宋丹敏的博客-CSDN博客_aop oop pop

    image-20220805144219915

    11.2 AOP在Spring中的作用?

    提供声明式事务:允许用户自定义切面!

    所有增删改完了之后都要通过commit()方法提交事务;

    • 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 ….
    • 切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类。
    • 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
    • 目标(Target):被通知对象。
    • 代理(Proxy):向目标对象应用通知之后创建的对象。
    • 切入点(PointCut):切面通知 执行的 “地点”的定义。
    • 连接点(JointPoint):与切入点匹配的执行点。

    img

    SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CyKDtVN0-1660011316883)(https://s2.loli.net/2022/08/05/zMWrPfNdXuU2GlC.png)]

    11.3 Spring中AOP如何实现?

    导AOP织入包 aspectjweaver

    pom.xml

    
    <dependency>
        <groupId>org.aspectjgroupId>
        <artifactId>aspectjweaverartifactId>
        <version>1.9.9.1version>
        <scope>runtimescope>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    log/Log.java

    package com.kuang.log;
    
    import org.springframework.aop.MethodBeforeAdvice;
    
    import java.lang.reflect.Method;
    
    
    /*
        MethodBeforeAdvice  前置教育
     */
    public class Log implements MethodBeforeAdvice {
    
        /*
           method: 要执行的目标对象的方法
           object: 参数
           target: 目标对象
         */
        public void before(Method method, Object[] objects, Object target) throws Throwable {
            System.out.println("【log】"+target.getClass().getName()+"的"+method.getName()+"被执行了");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    log/AfterLog.java

    package com.kuang.log;
    
    import org.springframework.aop.AfterReturningAdvice;
    
    import java.lang.reflect.Method;
    
    /*
        AfterReturningAdvice   后置通知
     */
    public class AfterLog implements AfterReturningAdvice {
    
        public void afterReturning(Object returnValue, Method method, Object[] objects, Object target) throws Throwable {
    
            System.out.println("【afterlog】执行了"+method.getName()+"方法,返回结果为:"+returnValue);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    service/UserService.java

    package com.kuang.service;
    
    public interface UserService {
    
        //业务层CRUD方法
        public void add();
        public void delete();
        public void update();
        public void query();
    
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    service/UserServiceImpl.java

    package com.kuang.service;
    
    public class UserServiceImpl implements UserService{
    
        public void add(){
            System.out.println("add了一个用户");
        }
    
        public void delete() {
            System.out.println("delete了一个用户");
        }
    
        public void update() {
            System.out.println("update了一个用户");
        }
    
        public void query() {
            System.out.println("query了一个用户");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    方式一:使用SpringAPI接口

    applicationContext.xml

    
    <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 id="userService" class="com.kuang.service.UserServiceImpl"/>
        <bean id="log" class="com.kuang.log.Log">bean>
        <bean id="afterLog" class="com.kuang.log.AfterLog">bean>
    
        
        
        
        <aop:config>
            
            
            <aop:pointcut id="pointcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/>
    
            
            <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
            <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    
    
        aop:config>
    beans>
    
    • 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

    方式二:自定义来实现AOP

    diy/DiyPointCut.java

    package com.kuang.diy;
    
    public class DiyPointCut {
    
        public void before(){
            System.out.println("====方法执行前====");
        }
        public void after(){
            System.out.println("====方法执行后====");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    applicationContext.xml

    
    <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 id="userService" class="com.kuang.service.UserServiceImpl"/>
        <bean id="log" class="com.kuang.log.Log">bean>
        <bean id="afterLog" class="com.kuang.log.AfterLog">bean>
    
        
    
        
        <bean id="diy"  class="com.kuang.diy.DiyPointCut"/>
    
        <aop:config>
            
            <aop:aspect ref="diy">
                
                <aop:pointcut id="point" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/>
                
                <aop:before method="before" pointcut-ref="point"/>
                <aop:after method="after" pointcut-ref="point"/>
    
            aop:aspect>
        aop:config>
    
    
    beans>
    
    • 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

    MyTest.java执行结果:

    image-20220808081750310

    方式三:使用注解实现

    diy/AnnotationPointCut.java

    package com.kuang.diy;
    
    
    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(* com.kuang.service.UserServiceImpl.*(..))")
        public void before(){
            System.out.println("====方法执行前====");
        }
    
        @After("execution(* com.kuang.service.UserServiceImpl.*(..))")
        public void after(){
            System.out.println("====方法执行后====");
        }
    
        @Around("execution(* com.kuang.service.UserServiceImpl.*(..))")
        public void around(ProceedingJoinPoint jp) throws Throwable {
            System.out.println("环绕前");
    
            //执行方法(前 Before())
            Object proceed = jp.proceed();
    
            System.out.println("环绕后");
    
            //Signature signature = jp.getSignature(); //获得签名
            //System.out.println("signature"+signature);
            //System.out.println("proceed:"+proceed);
    
    
            //执行方法(后 After())
        }
    
    }
    
    
    • 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

    applicationContext.xml

    
    <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 id="userService" class="com.kuang.service.UserServiceImpl"/>
        <bean id="log" class="com.kuang.log.Log">bean>
        <bean id="afterLog" class="com.kuang.log.AfterLog">bean>
    
       
    
        
        
        <bean id="applicationContext" class="com.kuang.diy.AnnotationPointCut"/>
        
        <aop:aspectj-autoproxy/>
    
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    MyTest.java

    import com.kuang.service.UserService;
    import com.kuang.service.UserServiceImpl;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MyTest {
    
        public static void main(String[] args) {
    
            //要用spring容器中的对象,先拿到ApplicationContext
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
            //从ApplicationContext中取出想要拿到的对象
            UserService userService = (UserService) applicationContext.getBean("userService");
            //通过拿到的类,调用方法
            userService.add();
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    MyTest.java运行结果:

    image-20220808094617307

    12、整合MyBatis

    步骤:

    1. 导入相关jar包

    2. 编写配置文件

    3. 测试

    pom.xml

    
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>spring-studyartifactId>
            <groupId>com.kuanggroupId>
            <version>1.0-SNAPSHOTversion>
        parent>
        <modelVersion>4.0.0modelVersion>
    
        <artifactId>spring-10-mybatisartifactId>
    
        <dependencies>
            
            <dependency>
                <groupId>junitgroupId>
                <artifactId>junitartifactId>
                <version>4.12version>
                <scope>testscope>
            dependency>
            
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>8.0.28version>
            dependency>
            
            <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatisartifactId>
                <version>3.4.2version>
            dependency>
            
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-webmvcartifactId>
                <version>5.3.18version>
            dependency>
            
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-jdbcartifactId>
                <version>5.2.2.RELEASEversion>
            dependency>
            
            <dependency>
                <groupId>org.aspectjgroupId>
                <artifactId>aspectjweaverartifactId>
                <version>1.9.9.1version>
            dependency>
            
            <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatis-springartifactId>
                <version>2.0.7version>
            dependency>
        dependencies>
    
    project>
    
    • 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

    12.1 回忆mybatis

    步骤:

    1. 编写实体类
    2. 编写核心配置文件
    3. 编写接口
    4. 编写Mapper.xml
    5. 测试

    pojo/Users.java

    package com.kuang.pojo;
    
    import lombok.Data;
    
    @Data  //省略写 get\set\构造\toString
    public class Users {
    
        private String id;
        private String name;
        private String pwd;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    mybatis-config.xml

    
    DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    
        <properties resource="jdbc.properties"/>
    
        <typeAliases>
            <package name="com.kuang.pojo"/>
        typeAliases>
    
    
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="${driver}"/>
                    <property name="url" value="${url}"/>
                    <property name="username" value="${username}"/>
                    <property name="password" value="${password}"/>
                dataSource>
            environment>
        environments>
        <mappers>
            <mapper resource="Mapper/UserMapper.xml"/>
        mappers>
    configuration>
    
    • 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

    jdbc.properties

    driver=com.mysql.cj.jdbc.Driver
    url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true
    username=root
    password=root
    
    • 1
    • 2
    • 3
    • 4

    mapper/UserMapper.java

    package com.kuang.mapper;
    
    import com.kuang.pojo.Users;
    
    import java.util.List;
    
    public interface UserMapper {
    
        public List<Users> selectUser();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    Mapper/UserMapper.xml

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.kuang.mapper.UserMapper">
    
        <select id="selectUser" resultType="users">
            select * from user
        select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    MyTest.java

    import com.kuang.mapper.UserMapper;
    import com.kuang.pojo.Users;
    import jdk.internal.util.xml.impl.Input;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    public class MyTest {
    
        @Test
        public void test1() throws IOException {
            //获取SqlsessionFactoryBuilder
            InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
            //读取流,获取sqlSessionFactory
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
            //获取sqlsession,设为true,自动提交
            SqlSession sqlSession = sqlSessionFactory.openSession(true);
    
            //获取要测试的类
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            //调用接口中要测试的方法
            List<Users> usersList = userMapper.selectUser();
            for (Users users : usersList) {
                System.out.println(users);
            }
    
            //关闭sqlsession
            sqlSession.close();
    
        }
    }
    
    
    • 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

    测试结果;

    image-20220808132012058

    12.2 方式一:MyBatis-Spring

    中文文档官网:mybatis-spring – http://mybatis.org/spring/zh/index.html

    • 将 MyBatis 代码无缝地整合到 Spring 中。

    • 允许 MyBatis 参与到 Spring 的事务管理之中,

      创建映射器 mapper 和 SqlSession 并注入到 bean 中,将 Mybatis 的异常转换为 Spring 的 DataAccessException

    • 可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。

    步骤:

    1. 导jar包

      mybatis-spring jar包 spring-jdbc jar包

    2. 编写数据源DataSource配置

    3. sqlSessionFactory

      引入数据源DataSource

      导入mybatisConfig核心配置文件

      绑定mapper

    4. sqlSessionTemplate 生成sqlSession

    5. 需要给接口加实现类【不同】

    6. 将自己写入实现类,注入MyBatis中

    7. 测试使用

    实例:

    导入mybatis-spring spring-jdbc jar包

    
    
    <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-jdbcartifactId>
        <version>5.3.22version>
    dependency>
    
    
    
    <dependency>
        <groupId>org.mybatisgroupId>
        <artifactId>mybatis-springartifactId>
        <version>2.0.7version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    pojo/User.java

    package com.kuang.pojo;
    
    import lombok.Data;
    
    @Data  //省略写 get\set\构造\toString
    public class Users {
    
        private String id;
        private String name;
        private String pwd;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    mapper/UserMapper.java

    package com.kuang.mapper;
    
    import com.kuang.pojo.Users;
    
    import java.util.List;
    
    public interface UserMapper {
    
        public List<Users> selectUser();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    mapper/UserMapperImpl.java

    package com.kuang.mapper;
    
    import com.kuang.pojo.Users;
    import org.mybatis.spring.SqlSessionTemplate;
    
    import java.util.List;
    
    public class UserMapperImpl implements UserMapper{
    
        //我们的所有操作在原来,都使用sqlSession来执行,现在,使用sqlSessionTemplated来执行;
        private SqlSessionTemplate sqlSession;
    
        //通过set方法注入
        public void setSqlSession(SqlSessionTemplate sqlSession) {
            this.sqlSession = sqlSession;
        }
    
        //输出列表
        public List<Users> selectUser() {
            //获取UserMapper对象
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            return mapper.selectUser();
        }
    }
    
    
    • 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

    resources/Mapper/UserMapper.xml

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.kuang.mapper.UserMapper">
    
        <select id="selectUser" resultType="users">
            select * from user
        select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    applicationContext.xml spring核心配置文件

    
    <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">
    
        
    
        <import resource="spring-dao.xml"/>
    
        
        <bean id="userMapper" class="com.kuang.mapper.UserMapperImpl">
            
            <property name="sqlSession" ref="sqlSession"/>
        bean>
    beans>
    <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">
    
        
    
        <import resource="spring-dao.xml"/>
    
        
        <bean id="userMapper" class="com.kuang.mapper.UserMapperImpl">
            
            <property name="sqlSession" ref="sqlSession"/>
        bean>
    beans>
    
    • 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

    mybatis-config.xml mybaits核心配置文件

    
    DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    
    
    
        
        <typeAliases>
            <package name="com.kuang.pojo"/>
        typeAliases>
    
        
    
    
    
    
    configuration>
    
    • 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

    spring-dao.xml spring整合mybatis配置文件

    
    <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="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
        bean>
    
        
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            
            <property name="dataSource" ref="dataSource" />
            
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
            
            <property name="mapperLocations" value="classpath:Mapper/*.xml"/>
        bean>
    
        
        <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
            
            <constructor-arg index="0" ref="sqlSessionFactory"/>
        bean>
    
        
        <bean id="userMapper" class="com.kuang.mapper.UserMapperImpl">
            
            <property name="sqlSession" ref="sqlSession"/>
        bean>
    beans>
    
    • 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

    MyTest.java

    import com.kuang.mapper.UserMapper;
    import com.kuang.pojo.Users;
    import jdk.internal.util.xml.impl.Input;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Test;
    import org.mybatis.spring.SqlSessionTemplate;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    public class MyTest {
    
    
        @Test
        public void test2(){
            //将bean中注册的类导入applicationContext
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            //从applicationContext中获取要操作的对象
            UserMapper userMapper = context.getBean("userMapper",UserMapper.class);
            //测试对象中的方法
            for (Users users : userMapper.selectUser()) {
                System.out.println(users);
            }
        }
    }
    
    
    • 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

    测试结果:

    image-20220808150957158

    12.3 方式二:extends SqlSessionDaoSupport

    mybatis-spring官网中文文档:http://mybatis.org/spring/zh/sqlsession.html

    UserMapperImpl2.java

    package com.kuang.mapper;
    
    import com.kuang.pojo.Users;
    
    import org.mybatis.spring.support.SqlSessionDaoSupport;
    
    import java.util.List;
    
    /*
        spring整合mybatis方式二: extends SqlSessionDaoSupport
    */
    public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
    
    
        public List<Users> selectUser() {
    
    /*        //获取sqlSessionTemplate,直接通过getSqlSession方法就可以获取
            SqlSession sqlSession = getSqlSession();
            //获取测试的接口类
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            //测试方法
            return mapper.selectUser();*/
    
            return getSqlSession().getMapper(UserMapper.class).selectUser();
        }
    }
    
    
    • 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

    applicationContext.xml

    <bean id="userMapper2" class="com.kuang.mapper.UserMapperImpl2">
        
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    bean>
    
    • 1
    • 2
    • 3
    • 4

    MyTest.java

        @Test
        public void test3(){
            //将bean中注册的类导入applicationContext
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            //从applicationContext中获取要操作的对象
            UserMapper userMapper = context.getBean("userMapper2",UserMapper.class);
            //测试对象中的方法
            for (Users users : userMapper.selectUser()) {
                System.out.println(users);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    测试结果:

    image-20220808152934745

    13、声明式事务

    13.1 回顾事务

    • 把一组业务当成一个业务来做;要么都成功,要么都失败!
    • 事务在项目开发中,十分的重要,设计到数据的一致性问题
    • 确保完整性和一致性

    事务的ACID原则:

    • 原子性 [atomicity](javascript:😉
      • 把一组业务当成一个业务来做;要么都成功,要么都失败!
    • 一致性 [consistency](javascript:😉
      • 资源加载,提交要保持一致,要么都提交,要么都失败;
    • 隔离性 [isolation](javascript:😉
      • 多个业务可能会操作同一个资源,防止数据损坏
    • 持久性 [durability](javascript:😉
      • 事务一旦提交,无论系统发生什么问题,结果都不会被影响,被持久化的写到存储器中!

    事务分为:声明式事务和编程式事务

    • 声明式事务:AOP
    • 编程式事务:需要在代码中,进行事务的管理

    13.2 声明式事务

    mybatis-spring中文文档:http://mybatis.org/spring/zh/transactions.html#configuration

    声明式事务

    配置声明式事务:

    在声明式的事务处理中,要配置一个切面,其中就用到了propagation 传播,表示打算对这些方法怎么使用事务,是用还是不用,

    其中propagation有七种配置,

    REQUIRED、 默认是REQUIRED 必须的

    SUPPORTS、

    MANDATORY、

    REQUIRES_NEW、

    NOT_SUPPORTED、

    NEVER、NESTED。

    image-20220808175430730

    实例:

    add(User user); 和 delete(int id); 两个方法要么都执行,要么都不执行;

    UserMapper.java

    package com.kuang.mapper;
    
    import com.kuang.pojo.User;
    
    import java.util.List;
    
    public interface UserMapper {
    
        public List<User> selectUser();
    
        /*
            模拟事务失败
         */
        //添加一个用户
        public int add(User user);
    
        //删除一个用户
        public int delete(int id);
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    UserMapperImpl.java

    package com.kuang.mapper;
    
    import com.kuang.pojo.User;
    import org.mybatis.spring.SqlSessionTemplate;
    import org.mybatis.spring.support.SqlSessionDaoSupport;
    
    import java.util.List;
    
    public  class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper {
    
        //我们的所有操作在原来,都使用sqlSession来执行,现在,使用sqlSessionTemplated来执行;
        private SqlSessionTemplate sqlSession;
    
    
        //通过set方法注入
        public void setSqlSession(SqlSessionTemplate sqlSession) {
            this.sqlSession = sqlSession;
        }
    
        //输出列表
        public List<User> selectUser() {
    
    
            //事务操作:插入和删除要么都执行,要么都不执行
            User user = new User(9,"10小王","123");
            UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
            mapper.add(user);
            mapper.delete(9);
    
    
            //获取UserMapper对象,调用对象中的方法
    
            return mapper.selectUser();
        }
    
        public int add(User user) {
            return getSqlSession().getMapper(UserMapper.class).add(user);
        }
    
        public int delete(int id) {
            return getSqlSession().getMapper(UserMapper.class).delete(id);
        }
    }
    
    
    • 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

    User.java

    package com.kuang.pojo;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data  // == get、set、toString
    @AllArgsConstructor // == 有参构造
    @NoArgsConstructor  // == 无参构造
    public class User {
    
        private int id;
        private String name;
        private String pwd;
    
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    UserMapper.xml

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.kuang.mapper.UserMapper">
    
        <insert id="add" parameterType="User">
            insert into user (id,name,pwd) value (#{id},#{name},#{pwd})
        insert>
    
        <delete id="delete" parameterType="int">
            delete from user where id=#{id}
        delete>
    
        <select id="selectUser" resultType="User">
            select id,name,pwd from user
        select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    applicationContext.xml

    
    <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"
           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/tx
            https://www.springframework.org/schema/tx/spring-tx.xsd">
    
    
    <import resource="spring-dao.xml"/>
    
        
        <bean id="userMapper" class="com.kuang.mapper.UserMapperImpl" >
            <property name="sqlSessionTemplate" ref="sqlSession" >property>
        bean>
    
        
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <constructor-arg name="dataSource" ref="dataSource" />
        bean>
        
        
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            
            
            <tx:attributes>
                <tx:method name="add" propagation="REQUIRED"/>
                <tx:method name="delete" propagation="REQUIRED"/>
                <tx:method name="update" propagation="REQUIRED"/>
                <tx:method name="query" read-only="true"/>
                <tx:method name="*" propagation="REQUIRED"/>
            tx:attributes>
        tx:advice>
    
        
        <aop:config>
            <aop:pointcut id="txPointCut" expression="execution(* com.kuang.mapper.*.*(..))"/>
            <aop:advisor advice-ref="txAdvice"  pointcut-ref="txPointCut"/>
        aop:config>
    
    beans>
    
    • 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

    mybatis-config.xml

    
    DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    
        
        <typeAliases>
            <typeAlias type="com.kuang.pojo.User" alias="User"/>
            <package name="com.kuang.pojo"/>
    
        typeAliases>
    
        
    
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    spring-dao.xml

    
    <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="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
        bean>
    
        
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            
            <property name="dataSource" ref="dataSource" />
            
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
            
            <property name="mapperLocations" value="classpath:Mapper/*.xml"/>
        bean>
    
        
        <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
            
            <constructor-arg index="0" ref="sqlSessionFactory"/>
        bean>
    
    
    beans>
    
    • 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

    测试成功,add和delete方法要么都执行了,要么都没有执行,没有出现add了一条用户信息后,数据库中多了一条用户信息,delete没有成功;

    主要就是银行取款存款操作;

    为什么需要事务?

    • 如果不配置事务,可能存在数据提交不一致的情况;

      比如:银行存钱操作

    • 如果我们不在spirng中去配置声明式事务,我们就需要在代码中手动配置事务;

    • 事务在项目的开发中十分重要,涉及到数据的完整性和一致性;

    • 事务的ACID原则;

  • 相关阅读:
    头歌实训答案:招聘数据分析
    PHP安装配置
    常用应届生Java开发笔试面试题(更新中)
    react18的使用技巧
    【C语言】联合union
    生产环境 Nginx后端服务大量TIME-WAIT的解决
    使用 Promise 来改写 JavaScript 的加载逻辑
    淘宝用户购物行为数据分析
    Pushgetway安装和使用
    基于复旦微JFMQL100TAI的全国产化FPGA+AI人工智能异构计算平台,兼容XC7Z045-2FFG900I
  • 原文地址:https://blog.csdn.net/MS_SONG/article/details/126242159