Bootstrap

Spring5-基础(完整流程)

1、Spring

1.1、简介

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

Spring理念:使现有的技术更加容易使用,整合了现有的技术框架

  • SSH:Struct2+Spring+Hibernate
  • SSM:SpringMVC+Spring+Mybatis

官网:Spring

Maven:

<!-- 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.springframework/spring-jdbc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>

1.2、优点

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

==总结:Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架 ==

1.3、组成

图片

构建一切,协调一切,连接一切

  • Spring Boot
    • 一个快速开放的脚手架
    • 基于SpringBoot可以快速的开发单个微服务
    • 约定大于配置
  • Spring Cloud
    • 基于SpringBoot实现的

学习SpringBoot的前提,需要完全掌握Spring及SpringMVC

2、IOC理论推导

在之前的业务中,用户的需求可能会影响我们原来的代码。我们需要根据用户的需求去修改原代码

代码量十分大,修改一次的成本代价十分昂贵

我们使用一个set接口实现,已经发生了革命性的变化

private UserDao userDao;

//利用set进行动态实现值的注入
public void setUserDao(UserDao userDao){
    this.userDao = userDao;
}
  • 之前,程序是主动创建对象,控制权在程序员手上
  • 使用了set注入后,程序不再有主动性,而是变成了被动的接受对象

这种思想,从本质上解决了问题,我们程序员不用再去管理对象的创建了。系统的耦合性大大降低,可以更加专注的在业务的实现上,这是IOC模型

IOC本质:

​ 控制反转IOC(Inversion of Control),是一种设计思想,DI(依赖注入)设计实现IOC的一种方法,也有人认为DI只是IOC的另一种说法。没有IOC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象创建转移给第三方,个人认为控制反转就是:获得依赖对象的方式反转了

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

3、HelloSpring

<bean id="hello" class="org.pojo.Hello">
    <property name="str" value="Spring"/>
</bean>

测试:

   public static void main(String[] args) {
        //获取Spring的上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        //我们的镀锌都在Spring管理了,我们需要使用,直接去取出来即可
        Hello hello = (Hello) context.getBean("hello");
        System.out.println(hello.toString());
    }

ClassPathXmlApplicationContext的继承关系

在这里插入图片描述

4、IOC创建对象的方式

  1. 使用无参构造创建对象,默认

  2. 假设我们要使用有参构造创建对象

    1. 下标赋值

      <bean id="user" class="org.pojo.User">
          <constructor-arg index="0" value = "jjq"></constructor-arg>
      </bean>
      
    2. 类型(不建议使用)

      <bean id="user" class="org.pojo.User">
          <constructor-arg type = "java.lang.String" value = "jjq"></constructor-arg>
      </bean>
      
    3. 参数名

      <bean id="user" class="org.pojo.User">
          <constructor-arg type = "name" value = "jjq"></constructor-arg>
      </bean>
      

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

5、Spring配置

5.1、别名

<alias name="hello" alias="h"/>

5.2、Bean的配置

<!--    使用Spring来创建对象,bean = 对象
        id = 变量名 也是唯一标识符
        class = new 的对象对应的全限定名:包名+类型
        name : 也是别名,而且name可以同时取多个别名
-->
    <bean id="hello" class="org.pojo.Hello" name="hello2,h">
        <property name="str" value="Spring"/>
    </bean>

5.3、import

这个import,一般用于团队开发使用,他可以将多个配置文件合并为一个

applicationContext.xml

<import resource="beans.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml"/>

使用的时候,直接使用总的配置就可以了

6、依赖注入

6.1、构造器注入

前文已经讲过了

6.2、Set注入(重点)

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

【环境搭建】

1.复杂类型

@Data
public class Address {
    private String adress;
}

2.真实测试对象

@Data
public class Student {
    private String name;
    private Address address;
    private String[] books;
    private List<String> hobbies;
    private Map<String,String> card;
    private Set<String> games;
    private Properties info;
}

3.beans.xml

    <bean id="student" class="org.pojo.Student">
<!--        第一种,普通值注入,value-->
        <property name="name" value="jjq"/>
    </bean>

4.测试类

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

完善注入信息

  <bean id="address" class="org.pojo.Address"/>

    <bean id="student" class="org.pojo.Student">
<!--        第一种,普通值注入,value-->
        <property name="name" value="jjq"/>
<!--        第二种,Bean注入,ref-->
        <property name="address" ref="address"/>
<!--        数组-->
        <property name="books">
            <array>
                <value>1</value>
                <value>2</value>
                <value>3</value>
                <value>4</value>
            </array>
        </property>
<!--        List-->
        <property name="hobbies">
            <list>
                <value>5</value>
                <value>6</value>
                <value>7</value>
            </list>
        </property>
<!--        map-->
        <property name="card">
            <map>
                <entry key="id" value="1"/>
                <entry key="num" value="2"/>
            </map>
        </property>
<!--        Set-->
        <property name="games">
            <set>
                <value>LOL</value>
                <value>LO</value>
                <value>L</value>
            </set>
        </property>
<!--        null-->
        <property name="wife">
            <null></null>
        </property>
<!--        Properties-->
        <property name="info">
            <props>
                <prop key="driver">211513677</prop>
                <prop key="url"></prop>
                <prop key="username">jjq</prop>
                <prop key="password">jjq</prop>
            </props>
        </property>
    </bean>

6.3、拓展方式注入

c命名和p命名空间注入

<!--p命名空间注入,可以直接注入属性的值:properties-->
<bean id="user" class="org.pojo.User" p:name="jjq" p:age="18"></bean>

<!--c命名空间注入,可以直接注入属性的值:construct-args-->
<bean id="user2" class="org.pojo.User" c:name="jjq" c:age="18"></bean>

注意点:p命名和c命名空间不能直接使用,需要导入xml约束

6.4、bean的作用域

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1.单例模式(Spring默认机制)

单例模式把对象放在pool中,需要的时候取出来,使用的都是同一个对象实例

<bean id="address" class="org.pojo.Address" scope="singleton"/>

2.原型模式

xxxxxxxxxx24 1try {2 userList = userService.getUserList(querUseryName, queryUserRole, currentPageNo, pageSize);3} catch (Exception e) {4 throw new RuntimeException(e);5}6req.setAttribute(“userList”,userList);7​8RoleServiceImpl roleService = new RoleServiceImpl();9List roleList = roleService.getRoleList();10req.setAttribute(“roleList”,roleList);11req.setAttribute(“totalCount”,totalCount);12req.setAttribute(“currentPageNo”,currentPageNo);13req.setAttribute(“totalPageCount”,totalPageCount);14req.setAttribute(“queryUserName”,querUseryName);15req.setAttribute(“queryUserRole”,queryUserRole);16​17//返回前端18try {19 req.getRequestDispatcher(“userlist.jsp”).forward(req,resp);20} catch (ServletException e) {21 throw new RuntimeException(e);22} catch (IOException e) {23 throw new RuntimeException(e);24}java

<bean id="address" class="org.pojo.Address" scope="prototype"/>

3.其余的request、session、application这些只能在web开发中使用到

7、Bean的自动装配

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

在Spring中有三种自动装配的方式

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

7.1、测试

1.环境搭建:一个有两个宠物

7.2、ByName自动装配

<!--byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid-->
    <bean id="people" class="org.pojo.People" autowire="byName">
        <property name="name" value="jjq"/>
    </bean>

7.3、ByType自动装配

<!--byType:会自动在容器上下文中查找,和自己对象属性类型相同的bean
	必须保证类型全局唯一-->
    <bean id="people" class="org.pojo.People" autowire="byType">
        <property name="name" value="jjq"/>
    </bean>

小结:

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

7.4、使用注解实现自动装配

jdk1.5支持注解,Spring2.5支持注解

The introduction of annotation-based configuration raised the question of whether this approach is “better” than XML.

要使用注解须知:

  1. 导入context约束

  2. 配置注解的支持<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>
    

    @AutoWired

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

    使用Autowried我们可以不用编写Set方法了,前提是自动装配的属性在IOC(Spring)容器中存在,且符合名字byName,先ByType再ByName

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

    @Data
    public class People {
        //如果显示定义了Autowired的required为false,说明这个对象可以为null,否则不允许为空
        @Autowired(required = false)
        private Cat cat;
        @Autowired
        private Dog dog;
        private String name;
    }
    

    如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解完成的时候,我们可以使用@Qualifier(value=“xxx”)去配置@Autowired的使用,指定唯一的bean对象注入

@Autowired
@Qualifier(value = "dog")
private Dog dog;

8、使用注解开发

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

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

  1. bean

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            https://www.springframework.org/schema/context/spring-context.xsd">
    
    
        <context:annotation-config/>
    </beans>
    
  2. 属性如何注入

    //等价于    <bean id="user" class="org.pojo.User"/>
    @Component
    @Data
    public class User {
    //    相当于<property name="name" value="jjq"/>
        @Value("jjq")
        public String name;
    }
    
  3. 衍生的注解

    • @Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层
      • dao【@Repository】
      • Service【@Service】
      • Controller【@Controller】
    • 这四个注解功能都是一样的,都是代码将某个类注册到Spring中,装配Bean
  4. 自动装配置

    @Autowired
    @Nullable
    @Resource
    
  5. 作用域

    @Scope("prototype")
    
  6. 小结

    • xml与注解:

      • xml更加万能,适用于任何场合,维护简单方便
      • 注解不是自己的类使用不了,维护相对负责
    • 最佳实践:

      • xml用来管理bean

      • 注解只负责完成属性的注入

      • 我们在使用的过程中只需要注意一个问题,必须要让注解生效,就要开启注解的支持

         <!--    指定要扫描的包,这个包下的注解就会生效-->
            <context:component-scan base-package="org.pojo"/>
            <context:annotation-config/>
        

9、使用Java的方式配置Spring

@Component
@Data
public class User {
//    相当于<property name="name" value="jjq"/>
    @Value("jjq")
    public String name;
}
//这个也是Spring容器托管,注册到容器中,因为他本来就是一个@Component
//@Configuration代表这是一个配置类
@Configuration
@ComponentScan("org.pojo")
@Import(MyConfig2.class)
public class MyConfig {

    //注册一个bean,就相当于我们之前写的bean标签
    //这个方法的名字,就相当于bean标签中的id属性
    //这个方法的返回值,就相当于bean标签中的class属性
    @Bean
    public User getUser(){
        return new User(); // 返回要注册到bean的对象
    }
}
public class MyTest {
    @Test
    public static void main(String[] args) {
        //如果完全使用了配置类方法去做,我们就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载
        ApplicationContext context = new ClassPathXmlApplicationContext(MyConfig.class);
        User getUser = (User) context.getBean("user");

        System.out.println(getUser.getName());
    }
}

10、代理模式

为什么要学习代理模式?

  • 因为这就是SpringAOP的底层【SpringAOP和SpringMVC】
  • 代理模式的分类
    • 静态代理
    • 动态代理

在这里插入图片描述

10.1、静态代理

角色分析:

  • 抽象角色:一般会使用接口或者抽象类来解决
  • 真实角色:被代理的角色
  • 代理角色:代理真实角色,代理真实角色后,会有一些附属操作
  • 客户:访问代理对象的人

代码步骤:

1.接口

package org.demo01;

//租房
public interface Rent {
    public void rent();
}

2.真实角色

package org.demo01;

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

3.代理角色

package org.demo01;

public class Proxy implements Rent{
    private Host host;

    public Proxy() {

    }

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

    @Override
    public void rent() {
        seeHouse();
        contract();
        host.rent();
        fare();
    }

    //看房
    public void seeHouse(){
        System.out.println("中介带你看房");
    }
    public void contract(){
        System.out.println("签合同");
    }
    //收中介费
    public void fare(){
        System.out.println("收中介费");
    }
}

4.客户端访问代理角色

package org.demo01;

public class Client {
    public static void main(String[] args) {
        //房东要租房子
        Host host = new Host();
        //代理,代理一般会有一些附属操作
        Proxy proxy = new Proxy(host);
        //你不用面对房东,直接找中介租房即可
        proxy.rent();
    }
}

代理模式的好处:

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

缺点:

  • 一个真实角色就会产生一个代理角色,代码量会翻倍-开发效率降低

10.2 、深入理解

在这里插入图片描述

10.3、动态代理

  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
    • 基于接口–JDK动态代理【这里使用的】
    • 基于类:cglib
    • java字节码实现:javasist

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

InvocationHandler

package org.demo02;

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 {

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

    public void seeHouse(){
        System.out.println("中介带看房子");
    }

}

动态代理的好处:

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

11、AOP

11.1、什么是AOP

什么是AOP:
全称是 Aspect Oriented Programming 即:面向切面编程。是OOP的延续,也是Spring框架中的一个重要内容,是函数式编程的一种衍生泛型。简单的说他就是把我们程序重复的代码抽取出来,在需要执行的时候使用动态代理技术在不修改源码的基础上,对我们的已有方法进行增强。AOP的底层就是动态代理,使用的技术就是反射

AOP能干什么:
举个例子,你想给你的网站记录用户访问日志:
对某些url,是不用记录的,而有些是需要记录的
如果你依然使用OOP,面向对象,
那你只能在那些url对应的Controller代码里面,一个一个写上日志记录的代码
而如果你使用了AOP呢?
无需在控制类添加代码,直接添加一个日志类,来进行无侵入式通过切面来记录日志。

AOP有什么优点:
1、减少重复代码
2、提高开发效率
3、维护方便

11.2、AOP在Spring中的作用

提供声明事务,允许用户自定义切面

AOP 相关术语

  • 横切面关注点:跨越应用程序多个模块的方法或功能,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点,

    • 如:日志,安全,缓存,事务等
  • Joinpoint(连接点):

    所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只支持方法类型的连接点。

  • Pointcut(切入点):
    所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义。

  • Advice(通知/增强):
    所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。
    通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。

  • Introduction(引介):
    引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行期为类动态地添加一些方
    法或 Field。

  • Target(目标对象):
    代理的目标对象。

  • Weaving(织入):
    是指把增强应用到目标对象来创建新的代理对象的过程。
    spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。

  • Proxy(代理):
    一个类被 AOP 织入增强后,就产生一个结果代理类。

  • Aspect(切面):
    是切入点和通知(引介)的结合。

img

11.3、使用Spring实现AOP

【重点】使用AOP织入,需要导入一个依赖包

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

方式一:使用Spring的API接口【主要是SpringAPI接口实现】

xml配置类

<!--    配置AOP:需要导入aop的越是-->
    <aop:config>
<!--        切入点
            expression:表达式
            execution(要执行的位置 * * * * *)
            -->
        <aop:pointcut id="pointcut" expression="execution(* org.service.UserServiceImpl.*(..))"/>
<!--        执行环绕增强-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>
public class Log implements MethodBeforeAdvice {
    //Method:要执行的目标对象的方法
    //Object:参数
    //o:目标对象
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println(o.getClass().getName()+"的"+method.getName()+"被执行了");
    }
}
public class AfterLog implements AfterReturningAdvice {
    //returnValue:返回值
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("执行了"+method.getName()+"方法返回结果为"+returnValue);
    }
}

方式二:自定义实现AOP【主要是切面定义】

xml配置类

    <!--方式二-->
    <bean id="diy" class="org.diy.DiyPointCut"/>

    <aop:config>
<!--        自定义切面 ref要引用的类-->
        <aop:aspect ref="diy">
<!--            切入点-->
                <aop:pointcut id="point" expression="execution(* org.service.UserServiceImpl.*(..))"/>
<!--            通知-->
                <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>
package org.diy;

public class DiyPointCut {
    public void before(){
        System.out.println("方法执行前");
    }

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

方式三:通过注解实现

xml配置类

<!--    方式三-->
    <bean id="annotationPointCut" class="org.diy.AnnotationPointCut"/>
<!--    开启注解支持-->
    <aop:aspectj-autoproxy/>
@Aspect
public class AnnotationPointCut {
    @Before("execution(* com.kuang.demo1.service.UserServiceImpl.*(..))")
    public void before() {
        System.out.println("=============方法执行前================");
    }

@After("execution(* com.kuang.demo1.service.UserServiceImpl.*(..))")
public void after() {
    System.out.println("============方法执行后==================");
}
 
//在环绕增强种,我们可以给定一个参数,代表我们要获取处理切入的点
@Around("execution(* com.kuang.demo1.service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint js) throws Throwable {
 
    System.out.println("==============环绕方法执行前================");
    //  执行方法
    Object proceed = js.proceed();
    System.out.println(proceed);
    System.out.println("==============环绕方法执行后================");
 
    //  获得签名
    Signature signature = js.getSignature();
    System.out.println("signature:" + signature);
}
}

12、Mybatis-Spring

什么是Mybatis-Spring?

​ MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession 并注入到 bean 中,以及将 Mybatis 的异常转换为 Spring 的 DataAccessException。 最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring

方式一:SqlSessionFactory

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
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
       ">

        <import resource="spring-dao.xml"/>

    <bean id="userMapper" class="com.jjq.mapper.UserMapperImpl">
        <property name="sqlSession" ref="sqlSession"/>
    </bean>

</beans>

spring-dao.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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 id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai"/>
        <property name="username" value="root"/>
        <property name="password" value="jinjiaqi123"/>
    </bean>

<!--    sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>

        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:UserMapper.xml"/>
    </bean>

<!--    sqlSessionFactory-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">

        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>


</beans>

方式二:SqlSessionDaoSupport

public class UserMapperImpl2 extends SqlSessionDaoSupport {
    public List<User> selectUser(){
        return getSqlSession().getMapper(UserMapper.class).selectUser();
    }
<bean id="userMapper2" class="com.jjq.mapper.UserMapperImpl2">
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

11、Spring-事务声明

<!--    配置声明式事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

<!--    结合AOP实现事务的织入-->
<!--    配置需求通知-->
    <tx:advice id="txAdvice" transction-manager="transactionManager">
<!--    给那些方法配置事务-->
<!--        配置事务的传播特性:new propagation-->
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
<!--    配置事务切入-->
    <aop:config>
        <aop:pointcut id="txPointCut" expression="execution(* com.jjq.mapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>
t<User> selectUser(){
        return getSqlSession().getMapper(UserMapper.class).selectUser();
    }
<bean id="userMapper2" class="com.jjq.mapper.UserMapperImpl2">
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

11、Spring-事务声明

<!--    配置声明式事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

<!--    结合AOP实现事务的织入-->
<!--    配置需求通知-->
    <tx:advice id="txAdvice" transction-manager="transactionManager">
<!--    给那些方法配置事务-->
<!--        配置事务的传播特性:new propagation-->
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
<!--    配置事务切入-->
    <aop:config>
        <aop:pointcut id="txPointCut" expression="execution(* com.jjq.mapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>
;