Spring

发布时间 2024-01-11 20:24:46作者: beiyuan666

准备工作

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

重点:控制反转(IOC)、面向切面(AOP)

控制反转(IOC)

代码举例说明控制反转(IOC)

  • 创建好几个文件 ,Hello是一个简单类,ApplicationContext.xml是Spring IOC 的一个配置文件,Mytest是测试类 ,如下:

image.png

  • Hello内容:
public class Hello {
    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Hello{" +
        "name='" + name + '\'' +
        '}';
    }
}
  • 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
  https://www.springframework.org/schema/beans/spring-beans.xsd">

  <!--  在Java中的对象,在spring中统称为bean  -->
  <!--
  java中创建对象(类):
  类型 变量名 = new 类型();
  Hello hello = new Hello();

  对于bean来说:
  id 相当于 变量名
  class 就是new 的对象(类)
  property相当于给对象(类)中的属性设置一个值
  -->
  <bean id="hello" class="com.zyp.pojo.Hello">
    <property name="name" value="hello spring"/>
  </bean>

</beans>
  • Mytest内容:
public class Mytest {
    public static void main(String[] args){
        //获取Spring的上下文对象
        //ClassPathXmlApplicationContext是通过“配置文件”获取上下文的实现类
        ApplicationContext context=new ClassPathXmlApplicationContext("ApplicationContext.xml");

        //我们的对象(类)都放在Spring中管理,我们需要使用的时候,直接去取出来
        Hello hello =(Hello)context.getBean("hello");	//根据注册的时候的id来取
        System.out.println(hello.toString());
    }
}

上面的过程就是控制反转(IOC):
控制:原本的是由程序本身来控制对象(类)的创建,现在使用Spring后,由Spring来控制创建。
反转:程序本身不创建对象(类),而变成被动接受。
依赖注入:就是利用set方法、构造器注入等方式来进行注入。

基于以上,我们就可以不再需要通过修改程序,去创建不同的类,以实现不同的操作。我们只需要对配置文件进行配置。IOC即对象皆由Spring来创建、管理、装配。

IOC创建对象方式

现在用一个简单的对象(User)来举例:

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;
    }

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

当我们没有显式写有参构造的时候,我们默认是存在无参构造的,这时我们在bean里注册的时候要用无参构造创建对象的方式。如果我们的类中有有参构造,且没有再添加无参构造,就需要使用有参构造创建方式。

  1. 使用无参构造创建对象,setter注入(默认!)<property name="name" value="这是bean无参构造方式创建对象"/>
  2. 使用有参构造方法
  • 下标索引创建:<constructor-arg index="0" value="这是有参构造的下标赋值"/>
  • 类型创建:<constructor-arg type="java.lang.String" value="这是有参构造的类型创建法"/>
  • 参数名赋值创建:<constructor-arg name="name" value="这是有参构造的参数名赋值创建法"/>

注意: 第二种基本不使用 ,第三种更常使用

Spring的配置

Bean的配置

<bean id="user" class="com.zyp.pojo.User" name="myuser1 myuser2,myuser3">

</bean>

id:是bean的唯一标识符,也是相当于对象的变量名
class:bean对象所对应的全限定名,包名+类
name:也是取别名,而且可以取多个别名,使用空格 逗号都能分隔

import

import一般用于团队开发使用,用于将外部的xml文件导入进来
<import resource="ApplicationContext.xml"/>

alias

用于给已注册的bean取别名
<alias name="user" alias="myuser"/>
说明:name="user"的user是已注册的bean的id

依赖注入

Set注入

案例演示:

  1. 准备一个类,里面包含很多复杂属性。
public class Student {
    private String name;
    private Address address;    //Address是我们自己写的地址类
    private String[] books;
    private List<String> hobbies;
    private Map<String,String> card;
    private Set<String> games;
    private String wife;
    private Properties info;
}

说明:类中有get set toString(),这里只是没有放上来。

  1. 接着,看看对于上面的Student类,我们在bean注册的时候要怎么使用set进行依赖注入
<!--这个bean会在下面被引用到-->
<bean name="address" class="com.zyp.pojo.Address">
  <property name="address" value="zhongguo"/>
</bean>

<bean name="student" class="com.zyp.pojo.Student">
  <!-- 1. 普通值的注入,value -->
  <property name="name" value="zyp"/>

  <!-- 2. bean的注入,ref -->
  <property name="address" ref="address"/>

  <!-- 3. 数组的注入 -->
  <property name="books">
    <array>
      <value>红楼梦</value>
      <value>水浒传</value>
      <value>三国演义</value>
      <value>西游记</value>
    </array>
  </property>

  <!-- 4. List的注入 -->
  <property name="hobbies">
    <list>
      <value>听歌</value>
      <value>写代码</value>
      <value>游戏</value>
    </list>
  </property>

  <!-- 5. Map的注入 -->
  <property name="card">
    <map>
      <entry key="身份证号码" value="123456"/>
      <entry key="出生日期" value="2003-07-10"/>
    </map>
  </property>

  <!-- 6. Set的注入 -->
  <property name="games">
    <set>
      <value>lol</value>
      <value>coc</value>
      <value>cf</value>
    </set>
  </property>

  <!-- 7. null的注入 -->
  <property name="wife">
    <null/>
  </property>

  <!-- 8. Properties的注入 -->
  <property name="info">
    <props>
      <prop key="url">www.ssss.com</prop>
      <prop key="username">beiyuan8</prop>
      <prop key="password">123456</prop>
    </props>
  </property>
</bean>

构造器注入

关于构造器注入,就是IOC创建对象的之有参构造方法创建,这里不多赘述。

P标签注入

可以看成就是set注入的一种封装,类中必须有get方法
p标签的使用,需要在配置文件中引入xmlns:p="http://www.springframework.org/schema/p"
image.png

演示:

  1. 写一个简单类User
public class User {
    private String name;
    private int age;
    private Address address;

    public String getName() {
        return name;
    }
}

说明:类中有get set toString(),这里只是没有放上来。

  1. xml中使用p命名空间注入
<?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:p="http://www.springframework.org/schema/p"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  https://www.springframework.org/schema/beans/spring-beans.xsd">

  <!--这个bean会在下面被引用到-->
  <bean id="address" class="com.zyp.pojo.Address">
    <property name="address" value="zhongguo"/>
  </bean>

  <!--p命名空间注入-->
  <bean id="user" class="com.zyp.pojo.User" p:name="zyp" p:age="20" p:address-ref="address"/>
  
</beans>
  1. 测试
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.toString());
    }
}

image.png

c标签注入

可以看成就是构造注入的一个封装,类中必须有有参构造方法
p标签的使用,需要在配置文件中引入:xmlns:c="http://www.springframework.org/schema/c"
image.png

演示:

  1. 写一个简单类User
public class User {
    private String name;
    private int age;
    private Address address;

    public User() {
    }

    public User(String name, int age, Address address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
}

说明:__类中有get set toString(),这里只是没有放上来。

  1. xml中使用c命名空间注入
<?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: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会在下面被引用到-->
  <bean id="address" class="com.zyp.pojo.Address">
    <property name="address" value="zhongguo"/>
  </bean>

  <!--c命名空间注入-->
  <bean id="user" class="com.zyp.pojo.User" c:name="zyp" c:age="20" c:address-ref="address"/>
  
</beans>
  1. 测试
public class Mytest {
    public static void main(String[] args){
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        Student student=(Student)context.getBean("student");
        User user=context.getBean("user", User.class);
        System.out.println(user.toString());
    }
}

image.png

自动装配

通过例子来演示:
准备三个类,Cat, Dog , People类

public class Cat {
    public void shout(){
        System.out.println("miaomiaomiao");
    }
}
public class Dog {
    public void shout(){
        System.out.println("wanwanwan");
    }
}
public class People {
    private Dog dog;
    private Cat cat;
    private String name;
}

注意:peple类中省略了set方法。

byName

byName会自动在容器中已注册的bean里面查找,和类中设置了的set方法的的属性名对应的的bean的id

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

<!-- byName会自动在容器中已注册的bean里面查找,和类中设置了的set方法的的属性名对应的的bean的id-->
<bean id="people" class="com.zyp.pojo.People" autowire="byName">
  <property name="name" value="hello world"/>
</bean>

上面的xml内容是为我们上面的三个类注册bean,可以看到我们使用了autowire="ByName"后,我们不再需要手动装配cat和dog,只需要bean的id能够对应上属性名就可以。前提是,这个属性拥有set方法
image.pngimage.png

byType

byType会自动在容器中已注册的bean里面查找,和类中属性的类型相同的bean

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

<!-- byType会自动在容器中已注册的bean里面查找,和类中属性的类型相同的bean-->
<bean id="people" class="com.zyp.pojo.People" autowire="byType">
  <property name="name" value="hello world"/>
</bean>

image.pngimage.png

注解实现自动装配

要使用注解,现有以下几个步骤:

  1. xml配置文件头部导入约束 (见下面代码块)
  2. xml配置文件中进行注解的支持
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context.xsd">

  <!-- 开启注解支持 -->
  <context:annotation-config/>

</beans>

使用:

  1. 在ioc容器中,我们只需要注册三个bean
<bean id="dog" class="com.zyp.pojo.Dog"/>
<bean id="cat" class="com.zyp.pojo.Cat"/>
<bean id="people" class="com.zyp.pojo.People">
	<property name="name" value="hello world!"/>
</bean>
  1. 在People类中,对应属性上使用@Autowired注解
public class People {
    @Autowired
    private Dog dog;
    @Autowired
    private Cat cat;
    private String name;
}

注意:此处省略了getter和setter方法

小结:对于@Autowired实现自动装配。当ioc容器中只注册了一个该类型的bean时,根据byType来实现装配。当ioc容器中注册存在多个同一类型的bean时,就根据byName来实现装配。

注解开发

注解说明

  1. @Component 组件,放在类上面,等价于

与之对应了几个衍生注解: 其实都是@Component,但是按照mvc三层架构,衍生不同的注解;

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

image.png

  1. @Value() 放在某个属性上面,相当于是属性的值的注入。等价于

image.png

  1. @Scope("") 放在某个类上面, 声明作用域

  2. @Autowired自动装配,前面介绍过。

xml与注解的最佳实践

xml注册bean, 注解完成属性的注入

使用java的方式配置spring

实例

准备一个pojo的类User

package com.zyp.pojo;
import org.springframework.stereotype.Component;

@Component
public class User {
    public String name="喜羊羊";

    public String getName() {
        return name;
    }

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

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

用Java实现配置类

  1. 创建一个类(MyConfiguration),作为配置类

image.png

  1. 使用注解@Configuration 以及 @Bean,以及@Import()
package com.zyp.configuration;

import com.zyp.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.zyp.pojo")  //可以使用ComponentScan进行包扫描
@Import(MyConfiguration2.class)
public class MyConfiguration {

    //相当于之前使用xml配置文件注册的一个bean标签
    // 方法的名字就是bean的id
    // 方法的返回值就是bean标签的class属性
    @Bean
    public User getUser(){
        return new User();
    }

}
  • @Configuration说明这是一个配置类,相当于我们之前的xml
  • @Bean 相当于之前使用xml配置文件注册的一个bean标签,方法的名字就是bean的id,方法的返回值就是bean标签的class属性。
  • @Import() 相当于导入另外一个配置类,合并在一起使用。

测试与使用

import com.zyp.configuration.MyConfiguration;
import com.zyp.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class MyTest {
    public static void main(String [] args){
        ApplicationContext context=new AnnotationConfigApplicationContext(MyConfiguration.class);
        User user =(User)context.getBean("getUser");
        System.out.println(user.getName());
    }
}

_说明: _如果使用的是java配置类,则需要使用AnnotationConfigApplicationContext。并且getBean()方法的参数是bean的id,也就是对应java配置类文件中的方法名。
image.png

代理模式

静态代理

角色分析:

  • 抽象角色:对应的是接口或者抽象类
  • 真实角色:对应了接口的实现类 (业务逻辑)
  • 代理角色:对接口实现类进行代理
  • 客户

在代码中的体现:

  1. 抽象角色:对应的是接口或者抽象类
public interface UserService {
        public void add();
        public void delete();
        public void update();
        public void query();
}
  1. 真实角色:对应了接口的实现类 (业务逻辑)
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("查询一个用户");
    }
}
  1. 代理角色:对接口实现类进行代理
public class UserServiceProxy implements UserService{
    UserServiceImpl userServiceimpl;

    public void setUserService(UserServiceImpl userService) {
        this.userServiceimpl = userService;
    }

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

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

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

    @Override
    public void query() {
        log("query");
        userServiceimpl.query();
    }

    //增加一个日志函数,不改变原有业务的代码,在代理类中进行功能增添
    public void log(String msg){
        System.out.println("[Debug] "+msg+" 被调用了");
    }
}

说明:增加一个日志函数,不改变原有业务的代码,在代理类中进行功能增添

  1. 客户
public class Client {
    public static void main(String [] args){
        UserServiceProxy userServiceProxy=new UserServiceProxy();   //代理类
        userServiceProxy.setUserService(new UserServiceImpl());     //通过代理类使用业务操作

        userServiceProxy.add();
        userServiceProxy.delete();
        userServiceProxy.update();
        userServiceProxy.query();
    }
}

image.png

动态代理

  • 动态代理角色和静态代理的角色一样
  • 动态代理分为两大类:基于接口的动态代理、基于类的动态代理

基于接口:jdk动态代理
基于类:cglib
java字节码实现:javasist

看一个使用动态代理的例子

  1. 抽象角色:接口(租房子这件事)
public interface Rent {
    public void rent();
}
  1. 真实角色(接口实现类):房东
public class Host implements Rent{
    @Override
    public void rent() {
        System.out.println("房东要出租房子!");
    }
}
  1. 写一个类ProxyInvocationHandler,由这个类自动生成代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//使用这个类自动生成代理类
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 );
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        look();
        Object result=method.invoke(rent, args);    //动态代理的本质, 就是使用反射机制
        fare();
        return result;
    }
    
    private void look(){
        System.out.println("中介带人看房");
    }
    private void fare(){
        System.out.println("中介收手续费");
    }
}

说明:look()函数和 fare()函数都是自己添加的,我们可以在Object invoke( )函数中添加其他代码

  1. 客户
public class Client {
    public static void main(String[] args){
        //真实角色(接口实现类)
        Host host = new Host();
        //这个类可以为我们后面生成代理类
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        //设置要代理的接口(传一个真实角色)
        pih.setRent(host);
        //获得一个动态生成的代理类
        Rent proxy = (Rent)pih.getProxy();

        proxy.rent();
    }
}

动态代理模板

//使用这个类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
    private Object target;  //被代理的接口

    //set方法设置要代理的接口
    public void setTarget(Object target) {
        this.target = target;
    }

    //生成得到代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(), this );
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        Object result=method.invoke(target, args);    //动态代理的本质, 就是使用反射机制
        return result;
    }
}

spring中的AOP实现

首先需要添加maven依赖:

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.9.6</version>
</dependency>
  1. 准备一个接口,和对应的接口实现类
public interface UserService {
    void add();
    void remove();
    void update();
    void query();
}
public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加了一个元素");
    }

    @Override
    public void remove() {
        System.out.println("删除了一个元素");
    }

    @Override
    public void update() {
        System.out.println("更新了一个元素");
    }

    @Override
    public void query() {
        System.out.println("查询一个元素");
    }
}
  1. 写一个自定义aop类
public class div_log {
    public void before(){
        System.out.println("=========方法执行前==========");
    }

    public void after(){
        System.out.println("=========方法执行后==========");
    }
}
  1. 在applicationContext.xml中进行配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:aop="http://www.springframework.org/schema/aop"

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

  <bean id="userService" class="com.zyp.service.UserServiceImpl"/>
  <bean id="log" class="com.zyp.log.div_log"/>

  <aop:config>
    <!-- 自定义切面: ref后面是要引用的类(bean)-->
    <aop:aspect ref="log">
      <!--定义切入点-->
      <!--execution()内部表达的是 返回值任意 service包下的UserServiceImpl类的所有函数,函数参数任意-->
      <aop:pointcut id="my_point" expression="execution(* com.zyp.service.UserServiceImpl.*(..))"/>
      <!--method是aop类中的某个方法, point-ref是表示method方法对哪个切入点执行-->
      <aop:before method="before" pointcut-ref="my_point"/>
      <aop:after method="after" pointcut-ref="my_point"/>
    </aop:aspect>
  </aop:config>

</beans>
  1. 测试与结果
public class My_test {
    public static void main(String[] args ){
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        //注意:动态代理的是接口
        UserService userService=(UserService) context.getBean("userService");
        userService.add();
        userService.query();
    }
}

image.png

spring中的注解实现aop

首先需要添加maven依赖:

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.9.6</version>
</dependency>
  1. 准备一个接口,和对应的接口实现类
public interface UserService {
    void add();
    void remove();
    void update();
    void query();
}
public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加了一个元素");
    }

    @Override
    public void remove() {
        System.out.println("删除了一个元素");
    }

    @Override
    public void update() {
        System.out.println("更新了一个元素");
    }

    @Override
    public void query() {
        System.out.println("查询一个元素");
    }
}
  1. 写一个自定义aop类,然后使用aop注解
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class div_log {
    @Before("execution(* com.zyp.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("=========(注解方式实现)方法执行前==========");
    }

    @After("execution(* com.zyp.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("=========(注解方式实现)方法执行后==========");
    }
}

  1. 在applicationContext.xml中进行配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"

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

    <bean id="userService" class="com.zyp.service.UserServiceImpl"/>

    <!--将aop类注册为一个bean-->
    <bean id="div_log" class="com.zyp.log.div_log"/>
    <!--开启注解支持-->
    <aop:aspectj-autoproxy/>

</beans>
  1. 测试与结果
public class My_test {
    public static void main(String[] args ){
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        //注意:动态代理的是接口
        UserService userService=(UserService) context.getBean("userService");
        userService.add();
        userService.query();
    }
}

image.png

spring整合jdbc

  1. 首先需要准备jar包,maven
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>5.3.29</version>
</dependency>
  1. 数据源与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"
  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
  http://www.springframework.org/schema/aop/spring-aop.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/study?useSSL=true&amp;useUnicode=true&amp;characterEncoding=GBK"/>
    <property name="username" value="root"/>
    <!-- 密码改成自己的 -->
    <property name="password" value="xxxxxxxxx"/>
  </bean>

  <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <!--后面可以绑定一些mybatis的配置-->
    <!--比如configuration、settings等等-->
    <property name="configLocation" value="classpath:mybatis-config.xml"/>
    <property name="mapperLocations" value="classpath:com/zyp/Mapper/*.xml"/>
  </bean>

  <bean id="userMapper" class="com.zyp.Mapper.UserMapperImpl2">
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
  </bean>

</beans>

说明:**_<property name="dataSource" ref="dataSource"/>_**_ 引用了前面的 _**_bean id="dataSource"_**
**_<property name="sqlSessionFactory" ref="sqlSessionFactory"/>_**_ 又引用了前面的 _**_bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"_**

  1. 接口配置UserMapper.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">

<!--namespace 命名空间 使用其绑定一个Dao(Mapper)的接口-->
<mapper namespace="com.zyp.Mapper.UserMapper">
  <!--一条查询语句-->
  <!--id对应 namespace绑定的接口中的函数。 resultType对应pojo的实体类-->
  <select id="selectUser" resultType="com.zyp.pojo.User">
    select * from study.user
  </select>
</mapper>
  1. 接口实现类
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
    @Override
    public List<User> selectUser() {
        return getSqlSession().getMapper(UserMapper.class).selectUser();
    }
}

//等价写法
//		SqlSession sqlSession=getSqlSession();
//      UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
//      return userMapper.selectUser();
//

说明:这里UserMapperImpl2类继承了SqlSessionDaoSupport,从这个类中,可以直接继承获得getSqlSession()函数,这个函数就是获取sqlSession。

  1. 测试与结果
public class My_test {
    @Test
    public void test(){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-dao.xml");
        UserMapper userMapper=context.getBean("userMapper", UserMapper.class);
        for(User user: userMapper.selectUser()){
            System.out.println(user);
        }
    }
}

image.png

  1. 目录结构

image.png