80.【Spring5】

Spring《解耦》

(一)、Spring 简介

https://springref.com/
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#spring-core
Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。

1.历史:

2022年: Spring 雏形形成。
2004年,Spring 一代正式发布。

2.Spring 目的

是现有的技术更加简单,本身是一个大杂烩,整合了现有的技术框架

SSH : Struct2 + Spring + Hibernate
SSM: SpringMvc+ Spring + Mybatis

3.Spring 引入

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.0</version>
</dependency>

4.优点

  • Spring 是一个免费开源的网站
  • Spring 是一个轻量级的,非入侵式的框架
  • 控制反转(IOC) ,面向切面编程(AOP)
  • 支持事务的处理,对框架整合的支持
    Spring 就是一个轻量级的控制反转(IOC)和切面编程(AOP)的框架

5.Spring 七大模块组成:

在这里插入图片描述

6.扩展(约定大于配置)

  • SpringBoot 一个快速开发的脚手架,可以快速开发一个微服务
  • SpringCloud 是基于SpringBoot实现的
  • 学习SpringBoot 的前提是完全掌握 SpringMVC Spring

(二)、IOC理论推导(Inversion of Contro)

1.以前的三层分级

  • Dao : 用于处理数据库的语句信息
    Dao层接口
package Com.Jsxs.Dao;

public interface UserDao {
    void getUser();
}

Dao层实现类01

package Com.Jsxs.Dao;

public class UserDaoImpl implements UserDao{
    @Override
    public void getUser() {
        System.out.println("用户信息,被查询");
    }
}

Dao层实现类02

package Com.Jsxs.Dao;

public class MysqlUserDaoImpl implements UserDao{

    @Override
    public void getUser() {
        System.out.println("mysql 调用用户数据");
    }
}
  • Servic :e 用于连接数据库,调用Dao
    业务接口层
package Com.Jsxs.Service;

public interface UserService {
    void getUser();
}

死型业务接口实现类

package Com.Jsxs.Service;

import Com.Jsxs.Dao.UserDao;
import Com.Jsxs.Dao.UserDaoImpl;

public class UserServiceImpl implements UserService{
    private UserDao userDao;
//   程序写死的状态
  public UserServiceImpl() {
       userDao=new UserDaoImpl();
  }
    @Override
    public void getUser() {
        userDao.getUser();
    }
}

活性业务层实现类(现在)

package Com.Jsxs.Service;

import Com.Jsxs.Dao.UserDao;
import Com.Jsxs.Dao.UserDaoImpl;

public class UserServiceImpl implements UserService{
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void getUser() {
        userDao.getUser();
    }
}

  • Servlet :用于调用Service 层
    -

2.现在对三层架构的更新

在这里插入图片描述

我们之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改代码。如果代码的数据量非常庞大,那么修改代码的成本的价值非常昂贵!!

	利用 set 实现数据的动态注入
	
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

程序的控制权由(ServiceImpl层) 转向了 (Servlet层);程序员----》用户自己
这种思想,从本质上解决了问题,我们程序员不用再去管理对象的创建了,系统的耦合性(关联)大大降低,可以更加的专注于业务的实现。
这一操作 实现了IOC控制权的反转
在这里插入图片描述

3.什么是IOC

ioc是由spring来负责控制对象的生命周期和对象间的关系。ioc容器(Inversion of Control,控制反转)是spring的核心,贯穿始终。Ioc意味着将你设计好的对象交给容器控制,主要控制了外部资源获取。

  • 控制反转是一种通过描述(XML 或 注解) 并通过第三方去生产或获取特定对象的方式,在Spring 中控制反转的是IOC容器,其实现方法是依赖注入(Dependency injection , DI)

(三)、HelloSpring

1.怎么使用Spring?

(1). 导入Spring 的版本jar包

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>6.0.2</version>
</dependency>

(2).导入资源文件包(XMI)

在这里插入图片描述

(3).编写配置文件

使用Spring 来创建对象,在Spring 这些都称为Bean
    bean: 就是对象; ===> new Hello();
    id: 就是变量名;
    class :全限定名
    property: 相当于给对象中的属性赋值
    name : 键,给谁赋值?
    value : 值,赋值什么
    contex.getBean(" id ")

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--    使用Spring 来创建对象,在Spring 这些都称为Bean
        bean: 就是对象; ===> new Hello();
        id: 就是变量名;
        class :全限定名
        property: 相当于给对象中的属性赋值
        name : 键,给谁赋值?
        value : 值,赋值什么
-->
    <bean id="hello" class="Com.Jsxs.pojo.Hello">
<!--        name 就是 类中的变量名, value : 随便起-->
        <property name="str" value="Spring"/>
    </bean>
</beans>

(4).第一个Spring

实体类

package Com.Jsxs.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@Data
@NoArgsConstructor
public class Hello {
    private String str;
}

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--    使用Spring 来创建对象,在Spring 这些都称为Bean
        bean: 就是对象; ===> new Hello();
        id: 就是变量名;
        class :全限定名
        property: 相当于给对象中的属性赋值
        name : 键,给谁赋值?
        value : 值,赋值什么
-->
    <bean id="hello" class="Com.Jsxs.pojo.Hello">
<!--        name 就是 类中的变量名, value : 随便起-->
        <property name="str" value="Spring"/>

    </bean>

</beans>

测试

import Com.Jsxs.pojo.Hello;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.ApplicationContext;

public class MyTest {
    public static void main(String[] args) {
//        绑定 beans.xml 配置文件 ,并获取Spring上下文的对象
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//        我们的对象现在都在Spring 中 进行管理了,我们要使,直接进去取出来就可以了
        Hello hello =(Hello) context.getBean("hello");
        System.out.println(hello.toString());
    }
}

在这里插入图片描述

2.雏形项目

Dao层接口

package Com.Jsxs.Dao;

public interface UserDao {
    void getUser();
}

Dao层实现类1

package Com.Jsxs.Dao;

public class MysqlUserDaoImpl implements UserDao{

    @Override
    public void getUser() {
        System.out.println("mysql 调用用户数据");
    }
}

Dao层实现类2

package Com.Jsxs.Dao;

public class UserDaoImpl implements UserDao{
    @Override
    public void getUser() {
        System.out.println("用户信息,被查询");
    }
}

Service接口

package Com.Jsxs.Service;

public interface UserService {
    void getUser();
}

Service接口的实现类一定要设置set 方法

package Com.Jsxs.Service;

import Com.Jsxs.Dao.UserDao;
import Com.Jsxs.Dao.UserDaoImpl;

public class UserServiceImpl implements UserService{
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void getUser() {
        userDao.getUser();
    }
}

Spring配置文件

ref : 引用Spring 中已经创建好的对象

value : 具体的值  ,赋值;基本数据类型。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="mysqlDaI" class="Com.Jsxs.Dao.MysqlUserDaoImpl"/>
    <bean id="userDaI" class="Com.Jsxs.Dao.UserDaoImpl"/>
    <bean id="userSev" class="Com.Jsxs.Service.UserServiceImpl">
<!--
        ref : 引用Spring 中已经创建好的对象
        value : 具体的值  ,赋值;基本数据类型。
-->
        <property name="userDao" ref="userDaI"/>
    </bean>
</beans>

在这里插入图片描述
测试

   ApplicationContext context = new ClassPathXmlApplicationContext("resource 目录下的资源");
import Com.Jsxs.Dao.MysqlUserDaoImpl;
import Com.Jsxs.Service.UserService;
import Com.Jsxs.Service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class test1 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        UserService userSev = (UserService) context.getBean("userSev");
        userSev.getUser();
    }
}

在这里插入图片描述

3.总结:

  • 有了Spring ,我们就彻底不用在程序中去改动了,要实现不同的操作只需要在XML配置文件中进行修改,所谓的IOC,就是:对象由Spring进行创建,管理,配置。
  • 依赖注入: 就是利用set方法进行注入
  • IOC: 是一种编程思想,由主动的编程变成了被动的编程
  • 反转: 程序本身不再创建对象,转变成被动的接受对象
  • 控制: 谁来控制对象的创建。
  • 一定要存在 set 方法,Spring主要依赖于set方法进行DI注入。
  • 如果使用Spring6 ,那么JDK的版本一定要高一点
  • 如果输出中文乱码,电脑右下角输出为 GBK,不要 UTF-8

(四)、IOC对象的创建方式

1.使用无参构造函数创建对象(不存在有参)

(1).反列(没有设置无参构造函数)

package Com.Jsxs.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
public class User {
    private String name;
    public User(String name){
        System.out.println("有参构造函数!!");
    }
    public void show(){
        System.out.println("name="+name);
    }
}

这里是引用

(2).正列 (有设置无参构造函数,没有设置有参构造)

实体类

package Com.Jsxs.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
public class User {
    private String name;
    public User(){
        System.out.println("无参构造函数!!");
    }
    public void show(){
        System.out.println("name="+name);
    }
}

配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="user" class="Com.Jsxs.pojo.User">
            <property name="name" value="吉士先生"/>
        </bean>
</beans>

测试

import Com.Jsxs.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) context.getBean("user");
        user.show();
    }
}

这里是引用

2.使用有参构造函数创建对象(不存在无参)

实体类

package Com.Jsxs.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
public class User {
    private String name;
    public void show(){
        System.out.println("name="+name);
    }
}

这里是引用

(1). 使用下标进行创建对象

index----> 有参构造函数的,属性从左向右排序

        <bean id="user" class="Com.Jsxs.pojo.User">
<!--     下标赋值        -->
            <constructor-arg index="0" value="吉士先生"/>
        </bean>

(2).使用类型进行创建对象

type: 指的是参数的类型,如果不是基本数据类型,那么需要使用权限定名

    <bean id="user" class="Com.Jsxs.pojo.User">
<!--    类型赋值     类型必须是全限定名   -->
        <constructor-arg type="java.lang.String" value="吉士先生"/>
    </bean>

(3).使用属性名进行创建对象

name: 指的是赋值属性的属性名叫什么

<!--    直接通过参数名进行赋值-->
    <bean id="user" class="Com.Jsxs.pojo.User">
        <constructor-arg name="name" value="吉士先生"/>
    </bean>

3. 使用有参和无参构造都存在的时候

有参和无参的方法都可以用,可以同时存在,不冲突;

4.总结

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

(五)、Spring 配置说明

1.alias(区分大小写)

大名和小名都可以指定

<alias name="需要修改的名字" alias="修改成什么"/>

实体类

package Com.Jsxs.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    public void show(){
        System.out.println("name="+name);
    }
}

配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="user" class="Com.Jsxs.pojo.User">
        <property name="name" value="小明"/>
    </bean>
    <alias name="user" alias="us"/>
</beans>

测试

import Com.Jsxs.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) context.getBean("us");
        user.show();
    }
}

在这里插入图片描述

2.bean(一个实体类一个bean)

  • id: 变量名
  • class : 类的全限定名
  • name: 可以起别名(不限制一个)
    <bean id="user" class="Com.Jsxs.pojo.User" name="us,se" >
        <property name="name" value="小明"/>
    </bean>

3.import

一般用于团队的开发,它可以将多个配置文件,导入合并为一个。
不同的开发人员,有不同的beans,最后合并到一个applicationContext;

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <import resource="beans.xml"/>

</beans>

在这里插入图片描述
在合并的时候,如果出现了同名且值i一样,那么就会产生覆盖。否则不会覆盖。

4.ref

意思就是:在实体类Address类中 new 一个对象叫做address2,
然后把new出来的address2赋值给实体类Student中属性名叫做address的。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="address2" class="Com.Jsxs.pojo.Address"/>
        <bean id="student" class="Com.Jsxs.pojo.Student">
<!--    第二种: Bean注入 ref-->
            <property name="address" ref="address2"/>
        </bean>
</beans>

(六)、依赖注入

1.构造器注入

章节四就是构造器注入(有参构造就是,无参不是)

2.Set方式注入【重点】

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

(1).环境搭建

复杂类型

package Com.Jsxs.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Address {
    private String address;
}

真实测试对象

package Com.Jsxs.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

@NoArgsConstructor
@AllArgsConstructor
@Data
public class Student {
    private String name;
    private Address address;  //类对象
    private String[] books;  //数组
    private List<String> hobbys;  // list集合
    private Map<String,String> card;  //键值
    private Set<String> games;  //set集合
    private String wife;	  //null
    private Properties info;  //配置
}

配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="student" class="Com.Jsxs.pojo.Student">
<!--    普通的set 方法注入        -->
            <property name="name" value="吉士先生"/>
        </bean>
</beans>

测试

import Com.Jsxs.pojo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Student student = (Student) context.getBean("student");
        System.out.println(student.getName());
    }
}

(2).开始真正实现

完善注入信息

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="address2" class="Com.Jsxs.pojo.Address"/>
        <bean id="student" class="Com.Jsxs.pojo.Student">
<!--    第一种:普通注入  value-->
            <property name="name" value="吉士先生"/>
<!--    第二种: Bean注入 ref-->
            <property name="address" ref="address2"/>
<!--    第三种: 数组注入 -->
            <property name="books">
                <array>
                    <value>红楼梦</value>
                    <value>西游记</value>
                    <value>水浒传</value>
                    <value>三国演义</value>
                </array>
            </property>
<!--    第四种: list注入 -->
            <property name="hobbys">
                <list>
                    <value></value>
                    <value></value>
                    <value>rap</value>
                </list>
            </property>
<!--    第五种:  Map注入        -->
            <property name="card">
                <map>
                    <entry key="身份证" value="1234567894545"/>
                    <entry key="银行卡" value="1234561235445"/>
                </map>
            </property>
<!--    第六种:  Set注入        -->
            <property name="games">
                <set>
                    <value>CF</value>
                    <value>CSGO</value>
                </set>
            </property>
<!--    第七种:  NULL        -->
            <property name="wife">
                <null/>
            </property>
<!--    第八种:  properties        -->
            <property name="info">
                <props>
                    <prop key="user">root</prop>
                    <prop key="password">121788</prop>
                </props>
            </property>
        </bean>

</beans>
Student(name=吉士先生,
address=Address(address=null),
books=[红楼梦, 西游记, 水浒传, 三国演义], 
hobbys=[唱, 跳, rap], 
card={身份证=1234567894545, 银行卡=1234561235445},
games=[CF, CSGO], 
wife=null, 
info={user=root, password=121788})

3.扩展式注入

p命名是Set方式注入,需要无参构造和set方法;c命名就是构造器注入,需要有参构造函数。

(1).P标签命名空间

p 命名空间注入,可以直接注入属性的值:

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

强转的操作,利用Class映射进行强转

User user = context.getBean("user",User.class);

实体类

package Com.Jsxs.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private int age;
}

配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--  p: 标签命名空间  -->
        <bean id="user" class="Com.Jsxs.pojo.User" p:name="吉士先生" p:age="21"/>
</beans>

测试

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("userBeans.xml");
        User user = context.getBean("user",User.class);
        System.out.println(user);
    }

在这里插入图片描述

(2).C标签命名空间

C通过构造器注入;

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

配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--  p: 标签命名空间  -->
        <bean id="user" class="Com.Jsxs.pojo.User" p:name="吉士先生" p:age="21"/>
        <bean id="user2" class="Com.Jsxs.pojo.User" c:name="吉士先生" c:age="28"/>
</beans>

(3).总结

  • p命名是Set方式注入,需要无参构造和set方法;
  • c命名就是构造器注入,需要有参构造函数。
  • 用之前,别忘记导入约束

4.Bean作用域

在这里插入图片描述

(1).单列模式(默认为单列 singleton)

在这里插入图片描述

配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
     
        <bean id="user2" class="Com.Jsxs.pojo.User" c:name="吉士先生" c:age="28"/>
</beans>

测试

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("userBeans.xml");
        User user = context.getBean("user2",User.class);
        User user1 = context.getBean("user2",User.class);
        System.out.println(user==user1);
    }

在这里插入图片描述

(2).原型模式(每次从容器中get的时候,都会产生一个对象)

在这里插入图片描述

配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

        <bean id="user2" class="Com.Jsxs.pojo.User" c:name="吉士先生" c:age="28" scope="prototype"/>
</beans>

测试

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("userBeans.xml");
        User user = context.getBean("user2",User.class);
        User user1 = context.getBean("user2",User.class);
        System.out.println(user==user1);
    }

在这里插入图片描述

(3).其他的模式

其他的模式在web应用开发中才会遇到。

(七)、Bean的自动装配

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

1.在Spring 中有三种装配的方式

  • 在XML中进行显示的配置 (章节七之前都是显示)
  • 在Java中进行显示的配置 (还没接触)
  • 隐式的自动装配bean (目前正在接触)

2.环境搭配

  • 一个人有两只宠物
    实体类
package Com.Jsxs.pojo;

public class Cat {
    public void shout(){
        System.out.println("喵喵喵喵喵...");
    }
}
package Com.Jsxs.pojo;

public class Dog {
    public void shout(){
        System.out.println("汪汪汪...");
    }
}
package Com.Jsxs.pojo;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class People {
    private Cat cat;
    private Dog dog;
    private String name;
}

配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--    三个类,也就是由三个bean -->
        <bean id="dog" class="Com.Jsxs.pojo.Dog"/>
        <bean id="cat" class="Com.Jsxs.pojo.Cat"/>

    <bean id="people" class="Com.Jsxs.pojo.People">
        <property name="name" value="川川"/>
        <property name="cat" ref="cat"/>
        <property name="dog" ref="dog"/>
    </bean>
</beans>

测试

import Com.Jsxs.pojo.People;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        People people = context.getBean("people", People.class);
        System.out.println(people);
        people.getDog().shout();
        people.getCat().shout();
    }
}

在这里插入图片描述

3.byName (根据id)

byName :会自动在容器上下文进行查找,和自己对象set方法后面的值对应的bean 的id 相等的话,那么就可以使用
eg: setName-----对应的是set后面的,而不是属性名----> name,

(1).正列

实体类

package Com.Jsxs.pojo;

public class Cat {
   public void shout(){
       System.out.println("喵喵喵喵喵...");
   }
}
package Com.Jsxs.pojo;

public class Dog {
    public void shout(){
        System.out.println("汪汪汪...");
    }
}
package Com.Jsxs.pojo;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class People {
    private Cat cat;
    private Dog dog;
    private String name;
}

配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--    三个类,也就是由三个bean -->
        <bean id="dog" class="Com.Jsxs.pojo.Dog"/>
        <bean id="cat" class="Com.Jsxs.pojo.Cat"/>
<!--
    byName :会自动在容器上下文进行查找,和自己对象set方法后面的值对应的bean 的id 相等的话,那么就可以使用
-->

    <bean id="people" class="Com.Jsxs.pojo.People" autowire="byName">
        <property name="name" value="川川"/>
<!--        <property name="cat" ref="cat"/>-->
<!--        <property name="dog" ref="dog"/>-->
    </bean>
</beans>

在这里插入图片描述

(2).反列

配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--    三个类,也就是由三个bean -->
        <bean id="dog" class="Com.Jsxs.pojo.Dog"/>
        <bean id="cat22" class="Com.Jsxs.pojo.Cat"/>
<!--
    byName :会自动在容器上下文进行查找,和自己对象set方法后面的值对应的bean 的id 相等的话,那么就可以使用
-->

    <bean id="people" class="Com.Jsxs.pojo.People" autowire="byName">
        <property name="name" value="川川"/>
    </bean>
</beans>

在这里插入图片描述

4.byType (根据class)

byType :会自动在容器上下文进行查找,和自己对象属性类型相同的bean

(1).正列

配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--    三个类,也就是由三个bean -->
        <bean id="dog" class="Com.Jsxs.pojo.Dog"/>
        <bean id="cat22" class="Com.Jsxs.pojo.Cat"/>
<!--
    byName :会自动在容器上下文进行查找,和自己对象set方法后面的值对应的bean 的id 相等的话,那么就可以使用
    byType :会自动在容器上下文进行查找,和自己对象属性相通的bean
-->

    <bean id="people" class="Com.Jsxs.pojo.People" autowire="byType">
        <property name="name" value="川川"/>
<!--        <property name="cat" ref="cat"/>-->
<!--        <property name="dog" ref="dog"/>-->
    </bean>
</beans>

测试

import Com.Jsxs.pojo.People;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        People people = context.getBean("people", People.class);
        System.out.println(people);
        people.getDog().shout();
        people.getCat().shout();
    }
}

在这里插入图片描述

(2).弊端

必须保证属性全局唯一

在这里插入图片描述

5.小结

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

(八)、注解实现自动装配

1.实现注解须知

  • 导入约束
xmlns:context="http://www.springframework.org/schema/context"
  • 配置注解支持
 http://www.springframework.org/schema/context
 https://www.springframework.org/schema/context/spring-context.xsd">
 <context:annotation-config/>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
      
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

</beans>

2.如何使用注解实现自动装配

(1).可以直接在属性上添加 注解

@Autowired

实体类

package Com.Jsxs.pojo;

public class Cat {
    public void shout(){
        System.out.println("喵喵喵喵喵...");
    }
}
package Com.Jsxs.pojo;

public class Dog {
    public void shout(){
        System.out.println("汪汪汪...");
    }
}
package Com.Jsxs.pojo;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class People {
    @Autowired
    private Cat cat;
    @Autowired
    private Dog dog;
    private String name;
}

配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:context="http://www.springframework.org/schema/context"

       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

        <context:annotation-config/>

        <bean id="dog" class="Com.Jsxs.pojo.Dog"/>
        <bean  id="cat" class="Com.Jsxs.pojo.Cat"/>
        <bean id="people" class="Com.Jsxs.pojo.People"/>
</beans>

测试

import Com.Jsxs.pojo.People;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        People people = context.getBean("people", People.class);
        System.out.println(people);
        people.getDog().shout();
        people.getCat().shout();
    }
}

在这里插入图片描述

2.@Autowired讲解(先类型后名字)

  • [ 直接在属性上使用即可,也可以在set方式上使用

  • [ 使用 @Autowired,我们可以不在编写Set方法了,前提是你这个自动装配的属性在IOC(Spring)容器中存在,且符合名字byType;

在这里插入图片描述

  • 这个注解借助的是映射,并不是set方法依赖注入

3.@Qualifier(value = “”) 需要一起使用

如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候,我们可以使用

(1).什么是自动装配的环境比较复杂?

比如: 因为我们注解自动装配用的是: ByType这个类型,所以我们在配置的时候不能同时出来两个类型相同的数bean。然而我们又想用,所以就出现了复杂类型的环境。

处理不了这种情况在这里插入图片描述
怎么解决:添加一个注解

实体类

package Com.Jsxs.pojo;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class People {
    @Autowired
    @Qualifier(value = "cat1111")
    private Cat cat;
    @Autowired
    private Dog dog;
    private String name;
}

配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:context="http://www.springframework.org/schema/context"

       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

        <context:annotation-config/>

        <bean id="dog11" class="Com.Jsxs.pojo.Dog"/>
        <bean  id="cat11" class="Com.Jsxs.pojo.Cat"/>
        <bean  id="cat1111" class="Com.Jsxs.pojo.Cat"/>
        <bean id="people" class="Com.Jsxs.pojo.People"/>
</beans>

在这里插入图片描述

4.@Resource自动装配(先名字后类型)

最大的区别: 就是如果遇到复杂的类型就不用一起写上面两个注解了,只要写上这一个注解就可以产生了。(整合了上面的注解)

@Resource(name = "cat2")

(1).进行测试Resource这个注解

package Com.Jsxs.pojo;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import javax.annotation.Resource;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class People {
    @Resource(name = "cat2")
    private Cat cat;
    @Resource
    private Dog dog;
    private String name;
}

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:context="http://www.springframework.org/schema/context"

       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

        <context:annotation-config/>

        <bean id="dog" class="Com.Jsxs.pojo.Dog"/>
        <bean id="cat" class="Com.Jsxs.pojo.Cat"/>
        <bean id="cat2" class="Com.Jsxs.pojo.Cat"/>
        <bean id="people" class="Com.Jsxs.pojo.People"/>
</beans>

在这里插入图片描述

5.小结

(1).@Resource和@Autowired的区别和@Qualifier

  1. 都是用来自动装配的,都可以放在属性的字段上
  2. @Autowired先ByType 后 ByName;而且必须这个对象存在
  3. @Resource先ByName 后 ByType;如果两个都找不到就报错
  4. @Qualifier必须要和@Autowired 共同用

(九)、使用注解开发

在Spring4之后,要使用注解开发,必须保证aop的包导入了

在这里插入图片描述

使用注解要导入Context约束,增加注解的支持

1.@Component《bean》

(1).搭建环境

(1).指定需要扫描的包,这个包下的注解就会生效
<context:component-scan base-package="Com.Jsxs.pojo"/>
(2).约束
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
xmlns:context="http://www.springframework.org/schema/context"
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
<!--    指定需要扫描的包,这个包下的注解就会生效-->
    <context:component-scan base-package="Com.Jsxs.pojo"/>
<!--    开启注解的驱动-->
    <context:annotation-config/>
</beans>

(2).Component注解

相当于
<bean id="user" class="Com.Jsxs.pojo.User"/>
配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
<!--    指定需要扫描的包,这个包下的注解就会生效-->
    <context:component-scan base-package="Com.Jsxs.pojo"/>
<!--    开启注解的驱动-->
    <context:annotation-config/>
</beans>

实体类

package Com.Jsxs.pojo;

import org.springframework.stereotype.Component;

@Component
// <bean id="user" class="Com.Jsxs.pojo.User"/>
public class User {
    public String name="吉士先生";
}

测试

import Com.Jsxs.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = context.getBean("user",User.class);
        System.out.println(user.name);
    }
}

在这里插入图片描述

2.@Value《属性注入》

相当于
<property name="name" value="川川"/>
实体类

package Com.Jsxs.pojo;

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

@Component
// <bean id="user" class="Com.Jsxs.pojo.User"/>
public class User {
    @Value("川川")
    public String name;
}

在这里插入图片描述

3.衍生的注解

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

  1. dao 【@Repository】
  2. service 【@Service】
  3. controller【@Controller】
  4. Component【@Component】
    这四个注解功能都是一样的,都是代表某个类注册到Spring中,装配Bean

4.自动装配

  1. @Autowired先ByType 后 ByName;而且必须这个对象存在
  2. @Resource先ByName 后 ByType;如果两个都找不到就报错
  3. @Qualifier必须要和@Autowired 共同联用

5.作用域

相当于在bean中注入的 scope

@Scope("prototype")
package Com.Jsxs.pojo;

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

@Component
// <bean id="user" class="Com.Jsxs.pojo.User"/>
@Scope("prototype")
public class User {
    @Value("川川")
    public String name;
}

6.小结

xml与注解

  • xml 更加万能,适用于任何场合!维护简单方便
  • 注解 不是自己的类是用不了,维护相对复杂!
    XML与注解最佳实践
  • XML用来管理Bean
  • 注解只负责完成属性的注入;
  • 我们在使用的过程中,只需要注意一个问题:必须让注解生效,就需要开启注解的支持
<!--    指定需要扫描的包,这个包下的注解就会生效-->
    <context:component-scan base-package="Com.Jsxs.pojo"/>
<!--    开启注解的驱动-->
    <context:annotation-config/>

7.注解类的全部步骤【】【】【】

xml中:
(1).配置约束
(2).开启注解支持
- 开启代理的注解支持: <aop:aspectj-autoproxy/>
- 开启注解的驱动: <context:annotation-config/>
(3).扫描包
 <context:component-scan base-package="Com.Jsxs"/>
类中: 
(1).这个类由Spring进行托管(bean)
@Component
(2).给类中的属性进行赋值
@Value
(3).设置作用域
@Scope
(4).对类中的复杂属性进行自动装配
@Autowired
(5).这个另类变成切面类
@Aspect 
(6).设置通知,通知里面的内容要是切入点
@Before("execution(* Com.Jsxs.service.UserServiceImp..*(..))")

(十)、使用Java的方式配置Spring

我们现在要完全不使用Spring的cml配置了,全权交给java来做;
JavaConfig 是Spring的一个子项目,在Spring4之后,他成为了一个核心功能。
在这里插入图片描述

1.搭建环境

配置文件类

package Com.Jsxs.Config;

import Com.Jsxs.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;

@Configuration
/*
    @Configuration: 代表这是一个配置类,和我们之前看的beans.xml一样
 */
@ComponentScan("Com.Jsxs.pojo")   //扫描包

@Import(JsxsConfig2.class)  //
public class JsxsConfig {
    /*
        1.如果开启包扫描,加载配置类以后,就可以通过反射拿到配置类中的对象了
        2.@Bean只写在方法上,返回的是一个对象,但一般不获取已经在容器中的休想
        3.@Bean 可以用于通过方法获取数据库连接池Connection这种对象
     */
    @Bean   //注册一个bean,就相当于我们之前写的bean标签,这个方法的名字相当于bean标签的id属性。方法的返回值就相当于bean中的class属性
    /*
    @Bean 告知Spring这个方法将会返回一个对象,这个对象要注册Spring应用上下文中的bean.通常方法体中包含了最终产生bean实列的逻辑
     */
    public User getUser(){
        return new User();
    }
}

实体类

package Com.Jsxs.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
/*
    @Component: 这个注解的意思,就是说明这个类被Spring接管了,注册到了容器中;表名一个类作为组件类,并告知Spring要为这个类创建bean
 */
public class User {
    @Value("川川")
    private String name;
}

测试类

import Com.Jsxs.Config.JsxsConfig;
import Com.Jsxs.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MyTest {
    public static void main(String[] args) {
//        ACA_C
        /*
        如果我们完全使用了配置类方式去做,我们九只能通过 ACA_C 进行获取
         */
        ApplicationContext context = new AnnotationConfigApplicationContext(JsxsConfig.class);
        User user = context.getBean("getUser", User.class);
        System.out.println(user.getName());
    }
}

在这里插入图片描述

2.详细讲解

  1. 配置类

  2. @Configuration: 代表这是一个配置类,和我们之前看的beans.xml一样

  3. @Bean:注册一个bean,就相当于我们之前写的bean标签,这个方法的名字相当于bean标签的id属性。方法的返回值就相当于bean中的class属性

  4. @ComponentScan(“Com.Jsxs.pojo”) 扫描包

  5. @Import(JsxsConfig2.class) 导入包

  6. 实体类

  7. @Component: 这个注解的意思,就是说明这个类被Spring接管了,注册到了容器中;表名一个类作为组件类,并告知Spring要为这个类创建bean

  8. 测试类

  9. 如果我们完全使用了配置类方式去做,我们就只能通过 ACAC 进行获取

3.小结

这种纯java的配置方式,在SpringBoot中随处可见!

(十一)、注解(总结)

  1. @SuppressWarnings(“all”) ====》镇压警告(方法和类上都可以)
  2. @Override ====》重写的注解 (方法上)
  3. @Target ====》注解的作用域 (方法 字段 类)
  4. @Target(value = {ElementType.METHOD}) //设置的只能在方法上使用
  5. @Retention 注解运行状态
  6. @Retention(value = RetentionPolicy.RUNTIME) //跑动的时候有效
  7. @Documented ====》 是否生成JavaDoc
  8. @Inherited ====》 是否进行子类继承父类
  9. @interface ====》自定义的注解

(十二)、代理模式

在这里插入图片描述

1.为什么要使用代理模式?

因为这就是SpringAop的底层;

  • 静态代理
  • 动态代理

2.静态代理

  • 抽象角色: 一般会使用接口和抽象类来解决(租房子这个事情)
  • 真实角色:被代理的角色(房东或则客户)
  • 代理角色:代理真是对象,代理真实角色后,我们一般会做一些附属操作。(中介)
  • 客户:访问代理角色的人
    静态代理: 代理对象和被代理对象都要实现接口,然后代理对象可以扩展功能。

(1).客户租房子案列

房东想出租一套房子,但是只想把钥匙给它,其他的什么事情都不想做。于是乎房东想到了中介可以帮助我们完成这些事情,然后就去找中介进行办理了手续。于是乎: 中介也了解房东的心思,不想管那么多的事情,于是就让房东交出房子的钥匙(rent)和身份证信息(host),然后就让房东走了。然后此时此刻有一个客户(cilent)找到了中介(proxy),在中介的介绍下,客户选择了房东名字叫做Host的这个房子,于是找代理进行办理,
在这里插入图片描述

接口

package com.Jsxs.demo1;

//出租房子这件事
public interface rent {
    void rent();
}

房东1

package com.Jsxs.demo1;

public class Host implements rent{
    @Override
    public void rent() {
        System.out.println("房东: 我要出租房子");
    }
}

中介

package com.Jsxs.demo1;
// 房东先拉过来 打一架;然后再继承房东的房子
public class proxy  implements rent{
    /*
        中介下面有很多的房东,然后中介只要调用出租房子这个接口,然后调取某个房东的房子去出租
     */
    private Host host;  //房东1

    public proxy() {
    }

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

    @Override
    public void rent() {
        host.rent();
        this.fare();
        this.regular();
    }
//    中介扩展
    public void fare(){
        System.out.println("中介收取费用");
    }
    public void regular(){
        System.out.println("中介签合同");
    }
}

客户

package com.Jsxs.demo1;

// 客人 :  租房子
public class Client {
    public static void main(String[] args) {
//    第一套方案 : 无中介直接找厂家
        Host host = new Host();
        host.rent();
//    第二套方案 : 不找房东 找中介
        proxy proxy = new proxy(host);
        proxy.rent();
    }
}

在这里插入图片描述

(2).代理模式的好处

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

(3).代理模式的缺点

  • 一个真实角色就会产生一个代理角色;代码量会进行翻倍·开发效率会变低。
    为什么说 一个真实角色就会产生一个代理对象? 是因为我们在中介(proxy)类中,只能设置一个房东,如果设置两个房东,那么我们的(proxy)构造函数要同时写两个房东的信息,然而客户只会选择一套房子进行操作,所以不能一个代理做两个房东的生意.

(4).代理模式真实案列

在这里插入图片描述
我们此次的实验是: 我们通过客户(Client)类,实现对实际业务的需求。我们这次要求在每次运行的时候都要进行添加日志的操作! 不要轻易改变公司的原有结构代码,因为接口不只是你在用,运用代理模式这样可以分工操作,所以我们不能对原有结构进行修改。
UserServic接口

package com.Jsxs.demo2;

public interface UserService {
    void add();
    void delete();
    void update();
    void query();
}

UserServic接口实现类

package com.Jsxs.demo2;

public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加了一个用户");
    }

    @Override
    public void delete() {
        System.out.println("删除了一个用户");
    }

    @Override
    public void update() {
        System.out.println("修改了一个用户");
    }

    @Override
    public void query() {
        System.out.println("查询了一个用户");
    }
}

客户类(实现)

package com.Jsxs.demo2;

public class Cilent {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        UserProxy userProxy = new UserProxy(userService);
        userProxy.add();
    }
}

代理类

package com.Jsxs.demo2;

public class UserProxy implements UserService{
    private UserService userService;

    public UserProxy(UserService userService) {
        this.userService = userService;
    }

    public UserProxy() {
    }

    @Override
    public void add() {
        log("add");
        userService.add();
    }

    @Override
    public void delete() {
        log("delete");
        userService.delete();
    }

    @Override
    public void update() {
        log("update");
        userService.update();
    }

    @Override
    public void query() {
        log("query");
        userService.query();
    }
    public void log(String msg){
        System.out.println("【Debug】"+"使用了"+msg+"方法");
    }
}

在这里插入图片描述

3.动态代理(代理的是接口)

在这里插入图片描述

  • 动态代理和静态代理角色一样
  • 动态代理类是动态生成的,不是我们自己手动写的。
  • 动态代理分为两类: 基于接口的动态代理,基于类的动态代理
  1. 基于接口 : JDK动态代理【我们在这里使用】
  2. 基于类 : cglib
  3. Java字节码 : javasist

1.环境搭配

(1).需要了解两个类

Proxy : 代理

InvocationHandler : 调用处理程序

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

(2).动态代理的好处

  • 可以使真实角色的操作更加存粹! 不用去关注一些公共的事务
  • 公共也就是交给代理角色,实现业务的分工
  • 公共业务发生扩展的时候,方便集中管理!
  • 一个 动态 代理类的是一个接口,一般对应的就是一类业务
  • 一个动态代理类 可以代替多个类,只要实现了同一个接口

(3).非完全动态代理

我是房东: 我想向外面租房子。想找个中介帮忙进行处理这件事情。
接口

package com.Jsxs.demo3;

//出租房子这件事
public interface rent {
    void rent();
}

房东实现接口

package com.Jsxs.demo3;

public class Host implements rent {
    @Override
    public void rent() {
        System.out.println("房东1: 我要向外出租房子");
    }
}

自动生成代理类

(1).我们在这里继承: 调用处理程序这个接口(InvocationHandler)
(2).创建真实对象(被代理对象)
(3).生成得到代理类:  类加载器;被代理对象的接口;调用处理程序;
Proxy.newProxyInstance(this.getClass().getClassLoader(),rent1.getClass().getInterfaces(),this);
(4).重写(InvocationHandler)接口的方法
(5).在重写的方法里面写: 目的是进行代理执行
 Object invoke = method.invoke(rent1, args);
package com.Jsxs.demo3;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/*
    我们用这个类,自动生成代理类
 */
public class proxyInvocationHandler implements InvocationHandler {
    private rent rent1;

    public void setRent1(rent rent1) {
        this.rent1 = rent1;
    }

    //    生成得到代理类
    public Object getPoxy(){
//        类加载器 ==》接口 ===》 InvocationHandler
        return  Proxy.newProxyInstance(this.getClass().getClassLoader(),rent1.getClass().getInterfaces(),this);
    }
//  处理代理实列,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHouse();
//        动态代理的实质就是使用反射机制
        Object invoke = method.invoke(rent1, args);
        write();
        return null;
    }
    public void seeHouse(){
        System.out.println("看房");
    }
    public void write(){
        System.out.println("签合同");
    }
}

客户类(实现类)

(1).创建真实对象(被代理对象)
(2).创建代理类
(3).向代理类里面写入被代理对象
(4).获取代理类; 强制类型转换成(接口的类型,不是接口的实现类)
package com.Jsxs.demo3;

public class Client {
    public static void main(String[] args) {
//真实对象
        Host host = new Host();
//代理角色 : 现在没有
        proxyInvocationHandler pih = new proxyInvocationHandler();
//通过调用程序处理角色来处理我们要调用的接口对象
        pih.setRent1(host);
        rent poxy = (rent) pih.getPoxy();  //这里的proxy就是动态生成的,我们没有写
        poxy.rent();
    }
}

在这里插入图片描述

(4).完全动态代理

只需要做出一些改变,就是引入被代理对象的时候,我们不进行指定的类型,而直接写出Object的类型就可以。
万能

package com.Jsxs.demo4;

import com.Jsxs.demo3.rent;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/*
    我们用这个类,自动生成代理类
 */
public class proxyInvocationHandler implements InvocationHandler {
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    //    生成得到代理类
    public Object getPoxy(){
//        类加载器 ==》接口 ===》 InvocationHandler
        return  Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
    }
//  处理代理实列,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//        动态代理的实质就是使用反射机制
        Object invoke = method.invoke(target, args);
        return null;
    }
}

客户

package com.Jsxs.demo4;

import com.Jsxs.demo2.UserService;
import com.Jsxs.demo2.UserServiceImpl;

public class Client {
    public static void main(String[] args) {
//        真实角色
        UserServiceImpl userService = new UserServiceImpl();
//        代理角色,不存在
        proxyInvocationHandler handler = new proxyInvocationHandler();
//        要动态处理的对象
        handler.setTarget(userService);
//        动态生成代理类
        UserService poxy = (UserService) handler.getPoxy();
        poxy.add();


    }
}

在这里插入图片描述

(5).总结

静态代理和动态代理的区别: 就是我们在中介类(代理类)的时候继承的东西不一样,静态代理类继承的接口是(被代理对象的接口类),动态代理类继承的是调用程序处理类(InvocationHandler)

(十三)、AOP

软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率

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

1.环境搭建

(1).导入一个jar包

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>

2.方式一:使用Spring的API实现【接口实现】

(1).要求不改变原有代码增加日志

UserService接口

package Com.Jsxs.service;

public interface UserService {
    void add();
    void delete();
    void update();
    void query();
}

UserService接口的实现

package Com.Jsxs.service;

public class UserServiceImp implements UserService{
    @Override
    public void add() {
        System.out.println("忝居埃就");
    }

    @Override
    public void delete() {

    }

    @Override
    public void update() {

    }

    @Override
    public void query() {

    }
}

前日志

(1).继承接口MethodBeforeAdvice
(2).重写方法
public void before(Method method, Object[] args, Object target){}
(3).参数的介绍
  method: 要执行目标对象的方法
  args: 参数
  target: 目标对象
package Com.Jsxs.log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class log implements MethodBeforeAdvice {
//    method: 要执行目标对象的方法
//    args: 参数
//    target: 目标对象
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName()+"的"+method.getName()+"的方法被执行了");
    }
}

后日志

(1).继承接口:AfterReturningAdvice
(2).重写方法
public void afterReturning
(3).参数的介绍
returnValue : 返回的结果

package Com.Jsxs.log;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class AfterLog implements AfterReturningAdvice {
//
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行了"+method.getName()+"方法的返回结果为:"+returnValue);
    }
}

Spring配置

(1).添加约束:
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
(2).接口除外都要写bean
	<bean id="user456" class="Com.Jsxs.service.UserServiceImp"/>
    <bean id="log" class="Com.Jsxs.log.log"/>
    <bean id="alog" class="Com.Jsxs.log.AfterLog"/>
(3).注册代理
(4).切入点:expression表达式===》execution(要执行的位置 *(修饰词)*(返回值)*(类名)*(方法名)*(参数))
<aop:pointcut id="pointcut" expression="execution(* Com.Jsxs.service.UserServiceImp.*(..))"/>
(5).执行环绕
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="alog" pointcut-ref="pointcut"/>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd

       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
">

<!--    注册bean-->
    <bean id="user456" class="Com.Jsxs.service.UserServiceImp"/>
    <bean id="log" class="Com.Jsxs.log.log"/>
    <bean id="alog" class="Com.Jsxs.log.AfterLog"/>
<!--    需要导入AOP的约束-->
<!--    注册代理-->
    <aop:config>
<!--        切入点:expression表达式===》execution(要执行的位置 *(修饰词)*(返回值)*(类名)*(方法名)*(参数)) -->
        <aop:pointcut id="pointcut" expression="execution(* Com.Jsxs.service.UserServiceImp.*(..))"/>
<!--        执行环绕增加-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="alog" pointcut-ref="pointcut"/>
    </aop:config>
</beans>

测试

import Com.Jsxs.service.UserService;
import Com.Jsxs.service.UserServiceImp;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService user =(UserService) context.getBean("user456");
        user.add();
    }
}

在这里插入图片描述

3.方式二:自定义实现AOP【切面定义】

配置文件

(1).自定义切面(ASPECT): 
<aop:aspect ref="切面类id">
(2).切入点(PointCut) execution(* Com.Jsxs.service.UserServiceImp.*(..))某个类的所有方法-->
<aop:pointcut id="point" expression="execution(*Com.Jsxs.service.UserServiceImp.*(..))"/>
(3).通知(Advice) method: 执行的方法名   pointcut-ref: 在哪执行 
 <aop:before method="方法" pointcut-ref="切入点id"/><aop:after method="方法" pointcut-ref="切入点id"/>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd

       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
">

<!--&lt;!&ndash;    注册bean&ndash;&gt;-->
    <bean id="user456" class="Com.Jsxs.service.UserServiceImp"/>
    <bean id="log" class="Com.Jsxs.log.log"/>
    <bean id="alog" class="Com.Jsxs.log.AfterLog"/>
    <bean id="diy" class="Com.Jsxs.diy.diy_font"/>
    <aop:config>
<!--        自定义切面-->
        <aop:aspect ref="diy">
<!--  切入点   execution(* Com.Jsxs.diy.diy_font..*(..))某个类的所有方法-->
            <aop:pointcut id="point" expression="execution(* Com.Jsxs.service.UserServiceImp..*(..))"/>
<!--   通知点      method: 执行的方法名   pointcut-ref: 在哪执行 -->
            <aop:before method="front" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>
</beans>

插入类

package Com.Jsxs.diy;

public class diy_font {
    public void front(){
        System.out.println("方法执行前...");
    }
    public void after(){
        System.out.println("方法执行后");
    }
}

测试

import Com.Jsxs.service.UserService;
import Com.Jsxs.service.UserServiceImp;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService user =(UserService) context.getBean("user456");
        user.add();
    }
}

在这里插入图片描述

4.方式三: 注解实现AOP

注解类

(1). 这个面变成切面类
@Aspect
(2).这个类由Spring托管,相当于创建一个bean
@Component
(3).设置通知,通知里面的内容要是切入点(在切入点前面)
@Before("execution(* Com.Jsxs.service.UserServiceImp..*(..))") 
(4).设置通知,通知里面的内容要是切入点(在切入点后面)
 @After("execution(* Com.Jsxs.service.UserServiceImp..*(..))")
(5).设置环绕
@Around("execution(* Com.Jsxs.service.UserServiceImp..*(..))")
(6).扫描包
<context:component-scan base-package="Com.Jsxs"/>
(7).开启proxy注解支持
<aop:aspectj-autoproxy/>
(8).开启注解支持
 <context:annotation-config/>
package Com.Jsxs;

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;
import org.springframework.stereotype.Component;

/**
 * 使用注解进行实现AOP的操作
 */

@Aspect // 这个面变成切面类
@Component //这个类由Spring托管,相当于创建一个bean
public class Annocation {
    @Before("execution(* Com.Jsxs.service.UserServiceImp..*(..))") //设置通知,通知里面的内容要是切入点
    public void before(){
        System.out.println("前-------");
    }
    @After("execution(* Com.Jsxs.service.UserServiceImp..*(..))")
    public void after(){
        System.out.println("后........");
    }
    @Around("execution(* Com.Jsxs.service.UserServiceImp..*(..))")  //在环绕增强中,我们可以给定一个参数,代表我们需要切入的点
    public void around(ProceedingJoinPoint proceedingJoinPoint){
        System.out.println("环绕前");
        Signature signature = proceedingJoinPoint.getSignature();  //获取签名
        System.out.println(signature);
//        执行方法
        try {
            Object proceed = proceedingJoinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("环绕后");
    }
}

配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd

       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
">
		扫描包
    <context:component-scan base-package="Com.Jsxs"/>
    <bean id="user456" class="Com.Jsxs.service.UserServiceImp"/>
    <bean id="log" class="Com.Jsxs.log.log"/>
    <bean id="alog" class="Com.Jsxs.log.AfterLog"/>
    <!--    开启注解支持-->
    <aop:aspectj-autoproxy/>
    <context:annotation-config/>
</beans>

测试

import Com.Jsxs.service.UserService;
import Com.Jsxs.service.UserServiceImp;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService user =(UserService) context.getBean("user456");
        user.add();
    }
}

在这里插入图片描述

5.方式一和方式二的区别

  • 方式一: 比较全(公司常用),但是填一个方法要写一个类
  • 方式二: 简便灵活,多个方法可以添加在一个类中
  • 方式三: 维护火葬场,注解一时爽

(十四)、整合Mybatis

http://mybatis.org/spring/zh/index.html
步骤:
1.导入相关jar包

  • junit
  • mybatis
  • mysql数据库驱动
  • Spring相关的
  • aop植入
  • mybatis-spring【新的】

2.编写配置文件
3.进行测试

1.回忆Mybatis

  1. 编写实体类
  2. 编写接口
  3. 编写核心配置文件
  4. 编写Mapper文件
  5. 编写工具类
  6. 进行测试

(1).搭建环境

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<!--configuration核心配置文件-->
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;charEncoding=UTF8"/>
                <property name="username" value="root"/>
                <property name="password" value="121788"/>
            </dataSource>
        </environment>
    </environments>
    <!--    每一个Mapper.xml都需要在Mybatis核心配置文件中注册-->
    <mappers>
      <mapper class="Com.Jsxs.Mapper.UserMapper"/>
    </mappers>
</configuration>

(2).编写工具类

package Com.Jsxs.Utils;

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 java.io.IOException;
import java.io.InputStream;

//  SqlSessionFactory---->sqlSession
public class MybatisUtil {
    private static SqlSessionFactory sqlSessionFactory;
    static {
        String resource = "mybatis-config.xml";
        try {
//  第一步:     获取SqlSessionFactory对象
            InputStream inputStream = Resources.getResourceAsStream(resource);
             sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //    既然有了sqlSessionFactory,顾名思义,我们就可以从中获得SqlSession的实列了
//    sqlSession完全包含了面向数据库执行SQL命令所需要的所有方法
    public static SqlSession getSqlSession(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        return sqlSession;
    }
}

(3).编写接口实现文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="Com.Jsxs.Mapper.UserMapper">
    
    <select id="selectUser" resultType="Com.Jsxs.pojo.User">
        select *from mybatis.user
    </select>
</mapper>

(4).测试

在这里插入图片描述

2.整合Mybatis方式一(没写工具类)

(0).配置相关的依赖包

【版本要求非常高:】
切记: spring-jdbc与spring-webmvc的版本号要一致

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
<!--        Spring链接数据库需要用到spring-jdbc-->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>

<!--   导入mybatis-spring依赖-->
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.2</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>
                <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
            <version>1.18.20</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

(1).编写数据源配置

可以顶替mybatis的核心配置文件

(1).引用类
id: 起一个类对象的变量名
class: 引用驱动管理数据资源这个类
(2).给类进行属性的赋值
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;charEncoding=UTF8"/>
<property name="username" value="root"/>
<property name="password" value="121788"/>
(3).这个类是JAR包自带的,不需要我们进行手动的创建
    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;charEncoding=UTF8"/>
        <property name="username" value="root"/>
        <property name="password" value="121788"/>
    </bean>

(2).建立sqlSessionFactory

可以顶替工具类

(1).注入sqlSessionFactory
引用SqlSessionTemplate类,并且利用构造器注入
(2).有且只能使用构造器进行注入
因为SqlSessionTemplate这个类中只有有参构造方法,没有无参构造方法;所以我们只能使用构造器进行注入
(3).这个类是JAR包自带的,不需要我们进行手动的创建
    <!--    SqlSessionTemplate: 就是我们需要用的sqlSession-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--       只能利用构造器注入 sqlSessionFactory,因为他没有set方法-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>

(4).接口添加实现类

(1).把工具传递给实现接口类中属性
给接口实现类进行注入
(2).
name: 接口实现类中的属性名
<!--创建bean-->
    <bean id="usermapperimpl" class="Com.Jsxs.Mapper.UserMapperImpl">
        <property name="sqlSessionTemplate" ref="sqlSession"/>
    </bean>

(5).将自己写的实现类,注入到Spring中

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
">

    <!--
DateSource: 使用Spring的数据源替换MyBatis的配置
我们这里使用Spring-Jdbc依赖提供的类 : org.springframework.jdbc.datasource.DriverManagerDataSource
-->
    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;charEncoding=UTF8"/>
        <property name="username" value="root"/>
        <property name="password" value="121788"/>
    </bean>
    <!--sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="datasource"/>
        <!--   绑定mybatis配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:Com/Jsxs/Mapper/*.xml"/>
    </bean>
    <!--    SqlSessionTemplate: 就是我们需要用的sqlSession-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--       只能利用构造器注入 sqlSessionFactory,因为他没有set方法-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>
<!--创建bean-->
    <bean id="usermapperimpl" class="Com.Jsxs.Mapper.UserMapperImpl">
        <property name="sqlSessionTemplate" ref="sqlSession"/>
    </bean>

</beans>

(6).接口实现类

(1).设置qlSessionTemplate属性
private SqlSessionTemplate sqlSessionTemplate;
(2).利用set注入
(3).进行工具的实现
UserMapper mapper = sqlSessionTemplate.getMapper(UserMapper.class);
List<User> userList = mapper.selectUser();
return userList;
package Com.Jsxs.Mapper;

import Com.Jsxs.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;

import java.util.List;

public class UserMapperImpl implements UserMapper{
//     原来,我们所有的操作,都是用sqlSession来执行,现在我们使用SqlSessionTemplate来执行
    private SqlSessionTemplate sqlSessionTemplate;

    public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
        this.sqlSessionTemplate = sqlSessionTemplate;
    }

    @Override
    public List<User> selectUser() {
        UserMapper mapper = sqlSessionTemplate.getMapper(UserMapper.class);
        List<User> userList = mapper.selectUser();
        return userList;
    }
}

(7).mybatis-config核心文件

mybatis核心配置文件几乎没用

(1).可以写别名
(2).可以写设置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<!--configuration核心配置文件-->
<configuration>

</configuration>

(8).测试类

import Com.Jsxs.Mapper.UserMapper;
import Com.Jsxs.Mapper.UserMapperImpl;
import Com.Jsxs.Utils.MybatisUtil;
import Com.Jsxs.pojo.User;
import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.io.Resources;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

public class MyTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
        UserMapper usermapper =(UserMapper) context.getBean("usermapperimpl");
        List<User> userList = usermapper.selectUser();
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

在这里插入图片描述

(10).提炼配置文件

spring-config

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
">

    <!--
DateSource: 使用Spring的数据源替换MyBatis的配置
我们这里使用Spring-Jdbc依赖提供的类 : org.springframework.jdbc.datasource.DriverManagerDataSource
-->
    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;charEncoding=UTF8"/>
        <property name="username" value="root"/>
        <property name="password" value="121788"/>
    </bean>
    <!--sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="datasource"/>
        <!--   绑定mybatis配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:Com/Jsxs/Mapper/*.xml"/>
    </bean>
    <!--    SqlSessionTemplate: 就是我们需要用的sqlSession-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--       只能利用构造器注入 sqlSessionFactory,因为他没有set方法-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>

</beans>

applicationContext文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
">
    <import resource="spring-dao.xml"/>
    <!--创建bean-->
    <bean id="usermapperimpl" class="Com.Jsxs.Mapper.UserMapperImpl">
        <property name="sqlSessionTemplate" ref="sqlSession"/>
    </bean>
</beans>

测试

import Com.Jsxs.Mapper.UserMapper;
import Com.Jsxs.Mapper.UserMapperImpl;
import Com.Jsxs.Utils.MybatisUtil;
import Com.Jsxs.pojo.User;
import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.io.Resources;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

public class MyTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        UserMapper usermapper =(UserMapper) context.getBean("usermapperimpl");
        List<User> userList = usermapper.selectUser();
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

在这里插入图片描述

(11).小结

  1. 比mybatis多一个接口实现类
  2. 实现图

在这里插入图片描述

3.整合Mybatis方式二(没写工具类)

(1).接口实现类要继承SqlSessionDaoSupport

(1).继承
(2).实现父类的方法
 getSqlSession()----》继承类的方法
(3).这个类SqlSessionDaoSupport,依赖自带的 
package Com.Jsxs.Mapper;

import Com.Jsxs.pojo.User;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.List;

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
    @Override
    public List<User> selectUser() {
        return getSqlSession().getMapper(UserMapper.class).selectUser();
    }
}

(2).mybatis-spring核心文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
">

    <!--
DateSource: 使用Spring的数据源替换MyBatis的配置
我们这里使用Spring-Jdbc依赖提供的类 : org.springframework.jdbc.datasource.DriverManagerDataSource
-->
    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;charEncoding=UTF8"/>
        <property name="username" value="root"/>
        <property name="password" value="121788"/>
    </bean>
    <!--sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="datasource"/>
        <!--   绑定mybatis配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:Com/Jsxs/Mapper/*.xml"/>
    </bean>
<!--    &lt;!&ndash;    SqlSessionTemplate: 就是我们需要用的sqlSession&ndash;&gt;-->
<!--    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">-->
<!--        &lt;!&ndash;       只能利用构造器注入 sqlSessionFactory,因为他没有set方法&ndash;&gt;-->
<!--        <constructor-arg index="0" ref="sqlSessionFactory"/>-->
<!--    </bean>-->
</beans>

(3).configContext

以下文件写死

<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
">
    <import resource="spring-dao.xml"/>
<!--    创建bean2-->
    <bean id="user2" class="Com.Jsxs.Mapper.UserMapperImpl2">
       <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>
</beans>

(4).测试

import Com.Jsxs.Mapper.UserMapper;
import Com.Jsxs.Mapper.UserMapperImpl;
import Com.Jsxs.Utils.MybatisUtil;
import Com.Jsxs.pojo.User;
import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.io.Resources;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

public class MyTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        UserMapper usermapper =(UserMapper) context.getBean("user2");
        List<User> userList = usermapper.selectUser();
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

在这里插入图片描述

(5).优点

  1. 可以在mybatis-spring中省略这个字段的创建
    <!--    SqlSessionTemplate: 就是我们需要用的sqlSession-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--       只能利用构造器注入 sqlSessionFactory,因为他没有set方法-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>
  1. 文件可写死
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>

(十五)、事务回顾

1.回顾事务

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

(1).ACID

  • 原子性
  • 一致性
  • 隔离性:多个数据操作同一个资源
  • 持久性: 事务一旦提交,结果都不会再影响

2.Spring的增删改业务实现

在这里插入图片描述

实体类

package Com.Jsxs.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
    private int id;
    private String name;
    private String pwd;
}

接口

package Com.Jsxs.Mapper;

import Com.Jsxs.pojo.User;

import java.util.List;

public interface UserMapper {
//    查询所有的用户
    List<User> selectUser();
//    添加一个用户
    int addUser(User user);
//    删除一个用户
    int deleteUser(int id);
}

接口实现类

package Com.Jsxs.Mapper;

import Com.Jsxs.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.List;


public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{
//    进行全部信息的查询
    @Override
    public List<User> selectUser() {
        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
        User user = new User(7,"说的","54545");
        mapper.addUser(user);
        mapper.deleteUser(7);
        return mapper.selectUser();
    }
//    进行数据的添加
    @Override
    public int addUser(User user) {
        return getSqlSession().getMapper(UserMapper.class).addUser(user);
    }
//   进行数据的删除
    @Override
    public int deleteUser(int id) {
        return getSqlSession().getMapper(UserMapper.class).deleteUser(id);
    }
}

接口配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="Com.Jsxs.Mapper.UserMapper">
<!--    进行数据的全部信息查询-->
    <select id="selectUser" resultType="Com.Jsxs.pojo.User">
        select *from mybatis.user
    </select>
<!-- 进行数据的添加-->
    <insert id="addUser" parameterType="Com.Jsxs.pojo.User">
        insert into user values(#{id},#{name},#{pwd})
    </insert>
<!--  进行数据的删除  -->
    <delete id="deleteUser" parameterType="int">
        delete from user where id=#{id}
    </delete>
</mapper>

mybatis核心文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<!--configuration核心配置文件-->
<configuration>

</configuration>

spring核心文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
">

<!--
DateSource: 使用Spring的数据源替换MyBatis的配置
我们这里使用Spring-Jdbc依赖提供的类 : org.springframework.jdbc.datasource.DriverManagerDataSource
-->
    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;charEncoding=UTF8"/>
        <property name="username" value="root"/>
        <property name="password" value="121788"/>
    </bean>
    <!--sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="datasource"/>
        <!--   绑定mybatis配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:Com/Jsxs/Mapper/*.xml"/>
    </bean>
    <!--    SqlSessionTemplate: 就是我们需要用的sqlSession-->
<!--    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">-->
<!--        &lt;!&ndash;       只能利用构造器注入 sqlSessionFactory,因为他没有set方法&ndash;&gt;-->
<!--        <constructor-arg index="0" ref="sqlSessionFactory"/>-->
<!--    </bean>-->

</beans>

汇总文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
">
    <import resource="spring-dao.xml"/>
    <!--创建bean1-->
    <bean id="user1" class="Com.Jsxs.Mapper.UserMapperImpl">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>
</beans>

测试

import Com.Jsxs.Mapper.UserMapper;
import Com.Jsxs.pojo.User;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

public class MyTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        UserMapper user1 = context.getBean("user1", UserMapper.class);
        List<User> userList = user1.selectUser();

        for (User user : userList) {
            System.out.println(user);
        }
    }
}

在这里插入图片描述

3.继承SqlSessionDaoSupport

  • 在spring核心文件中可以不用写第三个factory的豆
  • 自动帮我们进行提交事务,不用手动提交了

4.Spring声明事务

Spring中的事务管理

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

(1).基本要求

(1).接口

package Com.Jsxs.Mapper;

import Com.Jsxs.pojo.User;

import java.util.List;

public interface UserMapper {
//    查询所有的用户
    List<User> selectUser();
//    添加一个用户
    int addUser(User user);
//    删除一个用户
    int deleteUser(int id);
}

(2).mapper.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="Com.Jsxs.Mapper.UserMapper">
<!--    进行数据的全部信息查询-->
    <select id="selectUser" resultType="Com.Jsxs.pojo.User">
        select *from mybatis.user
    </select>
<!-- 进行数据的添加-->
    <insert id="addUser" parameterType="Com.Jsxs.pojo.User">
        insert into user values(#{id},#{name},#{pwd})
    </insert>
<!--  进行数据的删除  -->
    <delete id="deleteUser" parameterType="int">
        deletes from user where id=#{id}
    </delete>
</mapper>

(3).接口实现类【new】

 mapper.addUser(user);
mapper.deleteUser(7);.select方法中进行添加和删除;
package Com.Jsxs.Mapper;

import Com.Jsxs.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.List;


public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{
//    进行全部信息的查询
    @Override
    public List<User> selectUser() {
        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
        User user = new User(7,"说的","54545");
        mapper.addUser(user);
        mapper.deleteUser(7);
        return mapper.selectUser();
    }
//    进行数据的添加
    @Override
    public int addUser(User user) {
        return getSqlSession().getMapper(UserMapper.class).addUser(user);
    }
//   进行数据的删除
    @Override
    public int deleteUser(int id) {
        return getSqlSession().getMapper(UserMapper.class).deleteUser(id);
    }
}

(4).实体类

package Com.Jsxs.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
    private int id;
    private String name;
    private String pwd;
}

(5).mybatis核心文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<!--configuration核心配置文件-->
<configuration>

</configuration>

(6).Spring核心文件【new】

(1).命令开启事务
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <constructor-arg ref="datasource" />
</bean>
(2).结合Aop进行切面添加事务
(3).配置事务通知
<tx:advice id="txAdvice" transaction-manager="transactionManager">
(4).给哪些方法配置事务(需要添加约束) name: 需要添加事务接口的方法名 propagation 事务权限
 <tx:attributes>
            <tx:method name="addUser" propagation="REQUIRED"/>
            <tx:method name="deleteUser" propagation="REQUIRED"/>
            <tx:method name="selectUser" propagation="REQUIRED"/>
</tx:attributes>
(5).配置事务切入
<aop:config>
        <aop:pointcut id="pointcut" expression="execution(* Com.Jsxs.Mapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
</aop:config>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
">

<!--
DateSource: 使用Spring的数据源替换MyBatis的配置
我们这里使用Spring-Jdbc依赖提供的类 : org.springframework.jdbc.datasource.DriverManagerDataSource
-->
    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;charEncoding=UTF8"/>
        <property name="username" value="root"/>
        <property name="password" value="121788"/>
    </bean>
    <!--sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="datasource"/>
        <!--   绑定mybatis配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:Com/Jsxs/Mapper/*.xml"/>
    </bean>
    <!--    SqlSessionTemplate: 就是我们需要用的sqlSession-->
<!--    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">-->
<!--        &lt;!&ndash;       只能利用构造器注入 sqlSessionFactory,因为他没有set方法&ndash;&gt;-->
<!--        <constructor-arg index="0" ref="sqlSessionFactory"/>-->
<!--    </bean>-->

<!--    配置声明式事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <constructor-arg ref="datasource" />
    </bean>
<!--    结合AOP实现事物的植入-->
<!--配置事务通知:-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--
    给哪些方法进行配置事务
    配置事务的传播特性: propagation
    name: 指向配置事务的方法名
-->
        <tx:attributes>
            <tx:method name="addUser" propagation="REQUIRED"/>
            <tx:method name="deleteUser" propagation="REQUIRED"/>
<!--            <tx:method name="update" propagation="REQUIRED"/>-->
            <tx:method name="selectUser" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
<!--    配置事务切入-->
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* Com.Jsxs.Mapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
    </aop:config>

</beans>

(7).applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
">
    <import resource="spring-dao.xml"/>
    <!--创建bean1-->
    <bean id="user1" class="Com.Jsxs.Mapper.UserMapperImpl">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>
</beans>

(8).测试

import Com.Jsxs.Mapper.UserMapper;
import Com.Jsxs.pojo.User;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

public class MyTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        UserMapper user1 = context.getBean("user1", UserMapper.class);
        List<User> userList = user1.selectUser();
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

在这里插入图片描述

(9).效果展示

我们因为对查询的方法进行了切面(AOP)的操作,并且我们给事务增加,删除和查询都进行事务的管理,添加了事务。所以我们在进行设置查询的时候;查询的方法内涵着(添加和删除),我们故意在删除的时候埋下埋伏,验证成功事务设置成功;不会添加信息7
在这里插入图片描述
在这里插入图片描述

5.为什么要使用事务

  1. 如果不配置事务,可能存在数据提交不一致的情况
  2. 如果我们不在Spring中去配置声明式事务,我们就需要在代码中进行手动
  3. 事务在项目中十分重要,涉及到数据的一致性和完整性问题,不能马虎。

猜你喜欢

转载自blog.csdn.net/qq_69683957/article/details/128320800
今日推荐