Spring5 笔记

1.Spring 5

简介

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

2002 interface21

地址:https://spring.io/projects/spring-framework#learn

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

优点

  • 免费的容器
  • 是一个轻量级的、非入侵式的框架
  • 控制反转(IOC) 面向切面编程(AOP) ***
  • 支持事务

拓展

  • Spring Boot
    • 一个快速开发的脚手架
    • 基于SpringBoot可以快速的开发单个微服务
  • Spring Cloud
    • Spring Cloud是基于SpringBoot实现的

缺点:

发展太过于繁琐,然后违背了理念,配置过于繁琐

2.IOC

我们在设计Dao和Impl时 如果需求要发生改变 则会付出昂贵的代价

所以我们尝试在service层进行一个修改即 我们进行set方法来进行注入dao

public class UserServiceImpl implements UserService{
    UserDao userDao=new UserDaoImpl();
    @Override
    public void setUserDao(UserDao userDao) {
        this.userDao=userDao;
    }
    @Override
    public void getUser() {
        userDao.getUser();
    }
}
@Test
public void UserTest(){
    //用户实际上使用的业务层
    UserService userService = new UserServiceImpl();

    userService.setUserDao(new UserDaoMySqlImpl());
    userService.getUser();
}

这种思想从本质上解决了问题,不需要管理对象的创建,只需要专注在业务的实现上。

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

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

3.HelloSpring

<!--  这里开始使用Spring
        bean 相当于对象 相当于new Hello
        bean = > Hello hello = new Hello
           id 相当于变量名
           class 相对于new 的对象
           property 相当于变量
  -->
<bean id="hello" class="com.xue.pojo.Hello">
    <property name="str" value="Spring"/>
</bean>

test实

@Test
public void myTest() {
    //使用xml来加载 获取上下文的对象
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

    Hello hello = (Hello) context.getBean("hello");

    System.out.println(hello.toString());

}

另一个例子 注意类的引用要使用ref来引入

<bean id="mySqlImpl" class="com.xue.dao.UserDaoMySqlImpl">

</bean>
<bean id="oracleImpl" class="com.xue.dao.UserDaoOracleImpl">
</bean>

<bean id="userServiceImpl" class="com.xue.service.UserServiceImpl">
    <property name="userDao" ref="oracleImpl"/>
</bean>

它的实现

@Test
public void UserTest2(){
    //拿到容器
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

    UserService UserServiceBean = (UserService) context.getBean("userServiceImpl");

    UserServiceBean.getUser();
}

4.IOC 构造方法

无参

<bean id="user" class="com.xue.pojo.User">
    <property name="name" value="name1"/>
</bean>

<bean id="user2" class="com.xue.pojo.User">
</bean>

无论是否赋予参数 都会是调用无参的构造方式

有参构造

构造函数参数索引

您可以使用该index属性来明确指定构造函数参数的索引,如以下示例所示:

<!--  下标赋值  -->
<bean id="user3" class="com.xue.pojo.User">
    <constructor-arg index="0" value="xx"/>
</bean>

再这里我们进行了测试假如说我们仅仅传入了的是单个参数 则会自动匹配单个参数的构造方法

<bean id="user3" class="com.xue.pojo.User">
    <constructor-arg index="0" value="1"/>
    <constructor-arg index="1" value="xx"/>
</bean>

如果我们传入了两个参数,则会自动调用两个参数的set方法来进行构造

注意!

public User(int id) {
    this.id = id;
    System.out.println("User的有参构造 ID 一个参数");
}
public User(String name) {
    this.name = name;
    System.out.println("User的有参构造 name 一个参数");
}

假如说我们再构造的pojo具有两个这种对象,编译器并不会报错,但是再构造单个的参数的时候,将会出现一定的歧义

构造函数参数类型匹配(不推荐)

在上述情况下,如果通过使用type属性显式指定构造函数参数的类型,则容器可以使用简单类型的类型匹配,如以下示例所示:

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
</bean>

明显这里同样和上面一样,也会出现歧义

构造函数参数名称(推荐)

您还可以使用构造函数参数名称来消除歧义,如以下示例所示:

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg name="years" value="7500000"/>
    <constructor-arg name="ultimateAnswer" value="42"/>
</bean>

推荐这种方法,其中name是参数的名字

其他

有趣的是,容器里无论你是否需要他,他都会被调用。

并且调用的都是一份,且被初始化完毕。

通过实验可以晓得

User user2 = (User) context.getBean("user3");

User user3 = (User) context.getBean("user3");

System.out.println(user2 == user3);	//true
User user2 = (User) context.getBean("user3");

User user3 = (User) context2.getBean("user3");

System.out.println(user2 == user3); //false

所以看起来这种方法更像是我每次都会把xml变成一个类,用get来获取类中的已经构造好的内容。

5.Spring 的配置

别名

<alias name="user3" alias="user"/>

别名就是 把user可以等同于user3 在我看来作用不是很大

<bean id="user3" class="com.xue.pojo.User" name="user2,user,user4">
    <constructor-arg index="0" value="1"/>
</bean>

这里name也是别名,可能比alias有更多一定的别名

import

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

假如是项目多人开发,则可以import为一个总的 会存在id覆盖

6 DI 依赖注入

构造器注入

跟上面一样

set注入**

依赖注入

依赖,既bean对象的创建依赖于容器

注入,bean对象的所有属性,由容器来注入

这里做个回顾

mybatis用于数据库的连接和操作,即来作用于dao层的

spring在这里作用于pojo 即bean层

完善注入信息

<bean id="address" class="com.xue.pojo.Address">
    <property name="address" value="s"/>
</bean>

<!--最普通的值-->
<bean id="student" class="com.xue.pojo.Student">
    <property name="name" value="myName"/>
    <!--    ref注入    -->
    <property name="address" ref="address"/>
    <!--    数组注入    -->
    <property name="book">
        <array>
            <value>红楼梦</value>
            <value>三国</value>
            <value>西游记</value>
            <value>水浒传</value>
        </array>
    </property>
    <!--   list     -->
    <property name="hobbies">
        <list>
            <value>听课</value>
            <value>看电影</value>
            <value>睡觉</value>
        </list>
    </property>
    <!--   map    -->
    <property name="card">
        <map>
            <entry key="key1" value="value1"/>
            <entry key="key2" value="value1"/>
            <entry key="key3" value="value1"/>
        </map>
    </property>
    <!--set-->
    <property name="games">
        <set>
            <value>LOL</value>
            <value>AAA</value>
        </set>
    </property>
    <!--null-->
    <!-- <property name="info">-->
    <!--        <null/>-->
    <!-- </property>-->
    <property name="info">
        <props>
            <prop key="学号">123</prop>
            <prop key="性别">男性</prop>
        </props>
    </property>
</bean>

拓展方式:

有p命名空间和c命名空间两种

<!--
       导入p标签
       xmlns:p="http://www.springframework.org/schema/p"
       便可以使用:
      p:name="xx" p:id="4"
        类似于
      <property name="xx" value="s"/>

-->
    <bean id="user" class="com.xue.pojo.User" p:name="xx" p:id="4"/>

    <!--
         导入p标签
       xmlns:c="http://www.springframework.org/schema/c"
        便可以使用:
        c:name="xxx" c:id="sss"      
         类似于
        <constructor-arg name="name" value="xxx"/>
 
 -->
    <bean id="user2" class="com.xue.pojo.User" c:name="xxx" c:id="sss"/> 
    
    <bean id="user3" class="com.xue.pojo.User">
        <constructor-arg name="name" value="xxx"/>
    </bean>

注意P命名和C命名需要导入XML的约束

bean的作用域

ScopeDescription
singleton(Default) Scopes a single bean definition to a single object instance for each Spring IoC container.
prototypeScopes a single bean definition to any number of object instances.
requestScopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.
sessionScopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.
applicationScopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.
websocketScopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext.

singleton

<!--
 单例模式,即 每次出来的都是 一个
 Student student = (Student) context.getBean("student");
 Student student2 = (Student) context.getBean("student");

student==student2

-->
<bean id="user" class="com.xue.pojo.User" p:name="xx" p:id="4" scope="singleton"/>

prototype

<!--
·原型模式,即 每次出来的都是 一个心得对象
 Student student = (Student) context.getBean("student");
 Student student2 = (Student) context.getBean("student");

student!=student2

-->
<bean id="user" class="com.xue.pojo.User" p:name="xx" p:id="4" scope="prototype"/>

7 Bean的自动装配

  • spring会在上下文自动的寻找
  • 自动装配是Spring满足bean的一种方式

spring三种装配

  • 在xml中显示配置
  • 在java中配置
  • 隐式的自动装配

测试代码:

​ 一个人,有两个宠物

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


<bean id="people" class="xue.pojo.People">
    <property name="name" value="xxx"/>
    <property name="cat" ref="cat"/>
    <property name="dog" ref="dog"/>
</bean>

ByName自动装配

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

<bean id="people" class="xue.pojo.People" autowire="byName">
    <property name="name" value="xxx"/>
</bean>

会自动查找和自己的对象,在上下文一致的方法。

ByType

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

<bean id="people" class="xue.pojo.People" autowire="byType">
    <property name="name" value="xxx"/>
</bean>

上面两个各有弊端,其中第一个弊端就是,名字一定要上下文一样,类型则是上下文的类只能有一个

使用注解装配

基于注释的配置的引入提出了一个问题,即这种方法是否比XML“更好”。简短的答案是“取决于情况”。长的答案是每种方法都有其优缺点,通常,由开发人员决定哪种策略更适合他们。由于定义方式的不同,注释在声明中提供了很多上下文,从而使配置更短,更简洁。但是,XML擅长连接组件而不接触其源代码或重新编译它们。一些开发人员更喜欢将布线放置在靠近源的位置,而另一些开发人员则认为带注释的类不再是POJO,而且,配置变得分散并且难以控制。

使用注解须知

1.导入约束 context:annotation-config/

2.配置注解支持

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

    <context:annotation-config/>


</beans>

此后就可以这样

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

    <context:annotation-config/>


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

</beans>
@Autowired
Cat cat;

@Autowired
Dog dog;

String name;

@Autowired

这个这么使用

@Autowired
Cat cat;

我们来看一下特殊的情况

假如是xml中存在两个名字不一致的,类型一样的cat会如何

 expected single matching bean but found 2: cat1,cat2

​ 报错,找到了两个

这个时候我们来改变一个

<bean id="cat" class="xue.pojo.Cat">
    <property name="name" value="cat1"/>
</bean>
<bean id="cat2" class="xue.pojo.Cat">
    <property name="name" value="cat2"/>
</bean>
People{cat=Cat{name='cat1'}, dog=Dog{name='doog2'}, name='null'}

正常输入id一致的

<bean id="cat" class="xue.pojo.Dog">
    <property name="name" value="cat1"/>
</bean>
<bean id="cat2" class="xue.pojo.Cat">
    <property name="name" value="cat2"/>
</bean>

结果为:

expected single matching bean but found 2: cat,dog

报错

所以说

先会去根据名字来查找,如果查到了名字直接使用,并不会验证类型是否一致,如果要是查不到名字则会类型来获取,但是如果这时有多个类型则会直接报错

@Qualifier

@Qualifier(value = "cat1")
Cat cat;

自动装配,假如说无法通过Name Or Type来获取到的时候 可以使用Qualifier来指定

@Resource

 @Resource
 Dog dog;
<bean id="dog2" class="xue.pojo.Dog">
    <property name="name" value="doog2"/>
</bean>
<bean id="dog1" class="xue.pojo.Dog">
    <property name="name" value="doog1"/>
</bean>

No qualifying bean of type ‘xue.pojo.Dog’ available: expected single matching bean but found 2: dog2,dog1

<bean id="dog2" class="xue.pojo.Dog">
    <property name="name" value="doog2"/>
</bean>
<bean id="dog" class="xue.pojo.Dog">
    <property name="name" value="doog1"/>
</bean>

这个输出结果是

doog1

  <bean id="dog2" class="xue.pojo.Dog">
        <property name="name" value="doog2"/>
    </bean>
    <bean id="dog" class="xue.pojo.Cat">
	<!-- <property name="name" value="doog1"/>-->
    </bean>

这个直接就会进行报错

所以说我们的出来一个结论 在使用 @Resource开发时 先会去根据名字来查找,如果查到了名字直接使用,并不会验证类型是否一致,如果要是查不到名字则会类型来获取,但是如果这时有多个类型则会直接报错

下面是Spring开发文档的内容

从Spring Framework 5.0开始,您还可以使用@Nullable注释(任何包中的任何注释,例如,javax.annotation.Nullable来自JSR-305的注释),或仅利用Kotlin内置的null安全支持:

@Nullable
public People(@Nullable String name) {
    this.name = name;
}

即允许name为空

request为false则说明我们允许找不到装配,不抛异常

@Autowired(required = false)
Cat cat;

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

8 使用注解开发

在spring 4之后要使用注解开发,必须要保证注入aop的导入

bean

上一节有

属性

@Component

//Component 等价于一个<bean id="user" class="com.xue.pojo.User"/>

@Component
public class User {
    @Value("xue")
    public String name;
}

衍生的注解

@component 有几个衍生的注解,在web的开发中

@Controller
@Repository
@Service

自动装配

作用域

@Scope(“singleton”)

小结

xml 的配置文件可以用于任何地方
注解 不是自己类使用不了,维护也很复杂

xml来管理bean
注解负责完成属性的注入

要想要注解生效一定要在xml里增加扫描包

<!--   指定要扫描的包 -->
<context:component-scan base-package="com.xue"/>

使用Java的方式来配置Spring

如果完全不使用Spring的xml,完全交给Java来实现

JavaConfig变成了新的功能

@Configuration

9 代理模式

为什么要学代理模式?Spring AOP 的底层

分为静态代理和动态代理

静态代理

角色分析

​ 抽象角色:用接口或者抽象类来解决

​ 真实角色:被代理的角色

​ 代理角色:代理真实的角色,代理角色后,我们一般做一些附属操作

代理模式的好处

可以让用户的操作更加纯粹

可以实现分工

方便扩展

缺点

一个角色会形成一个代理对象,但是代码的量会增加。

动态代理

动态代理和静态代理角色是一样的

动态代理的代理类是动态生成的,不是直接写出来的

1 基于接口 JDK

2 基于类

3 基于Java ssist

两个类

proxy

InvocationHandler

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

    • Modifier and TypeMethod and Description
      Objectinvoke(Object proxy, 方法 method, Object[] args) 处理代理实例上的方法调用并返回结果。
  • Proxy提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。

    为某个接口创建代理Foo

      InvocationHandler handler = new MyInvocationHandler(...);
         Class<?> proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class);
         Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class).
                         newInstance(handler); 
    

    或更简单地:

      Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
                                              new Class<?>[] { Foo.class },
                                              handler); 
    

代理类

public class ProxyInvocationHandler implements InvocationHandler {

    private Object target;

    public Object getTarget() {
        return target;
    }

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

}

10 AOP

让我们首先定义一些重要的AOP概念和术语。这些术语不是特定于Spring的。不幸的是,AOP术语并不是特别直观。但是,如果Spring使用其自己的术语,那将更加令人困惑。

  • 方面:跨多个类的关注点的模块化。事务管理是企业Java应用程序中横切关注的一个很好的例子。在Spring AOP中,方面是通过使用常规类(基于模式的方法)或使用注释进行@Aspect注释的常规类 (@AspectJ样式)来实现的。
  • 连接点:在程序执行过程中的一点,例如方法的执行或异常的处理。在Spring AOP中,连接点始终代表方法的执行。
  • 建议:方面在特定的连接点处采取的操作。不同类型的建议包括“周围”,“之前”和“之后”建议。(建议类型将在后面讨论。)包括Spring在内的许多AOP框架都将建议建模为拦截器,并在联接点周围维护一连串的拦截器。
  • 切入点:与连接点匹配的谓词。建议与切入点表达式关联,并在与该切入点匹配的任何连接点处运行(例如,执行具有特定名称的方法)。切入点表达式匹配的连接点的概念是AOP的核心,默认情况下,Spring使用AspectJ切入点表达语言。
  • 简介:代表类型声明其他方法或字段。Spring AOP允许您向任何建议的对象引入新的接口(和相应的实现)。例如,您可以使用简介来使Bean实现 IsModified接口,以简化缓存。(在AspectJ社区中,介绍被称为类型间声明。)
  • 目标对象:一个或多个方面建议的对象。也称为“建议对象”。由于Spring AOP是使用运行时代理实现的,因此该对象始终是代理对象。
  • AOP代理:由AOP框架创建的对象,用于实施方面合同(建议方法执行等)。在Spring Framework中,AOP代理是JDK动态代理或CGLIB代理。
  • 编织:将方面与其他应用程序类型或对象链接以创建建议的对象。这可以在编译时(例如,使用AspectJ编译器),加载时或在运行时完成。像其他纯Java AOP框架一样,Spring AOP在运行时执行编织。

基于XML的AOP

导入的包

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

声明

可以使用<aop:aspect>元素声明一个方面,并使用ref属性来引用支持Bean ,如以下示例所示:

<aop:config>
    <aop:aspect id="myAspect" ref="aBean">
        ...
    </aop:aspect>
</aop:config>

<bean id="aBean" class="...">
    ...
</bean>

声明切入点

您可以在<aop:config>元素内声明一个命名的切入点,从而使切入点定义可以在多个方面和顾问程序之间共享。

可以定义代表服务层中任何业务服务的执行的切入点:

<aop:config>

    <aop:pointcut id="businessService"
        expression="execution(* com.xyz.myapp.service.*.*(..))"/>

</aop:config>

宣告

<!--使用API接口-->
<!-- 配置AOP   -->
<aop:config>
    <!--    需要一个切入点  expression 要切入的位置(要执行的位置!修饰词,返回值 类名 方法名 参数)  -->
    <aop:pointcut id="pointcut1" expression="execution(* com.xue.service.UserServiceImpl.*(..)  )"/>
    <!--执行环绕增强-->
    <aop:advisor advice-ref="log" pointcut-ref="pointcut1"/>
    <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut1"/>
</aop:config>

测试

public class Mytest {
    public static void main(String[] args) {
        //获取
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        UserService userService = (UserService) context.getBean("userService");
        userService.add();


    }
}

方法二 用一个类

就是在宣告的时候更改一下

<!--  方式二  -->
<bean id="diy" class="com.xue.diy.DiyPointCut"/>
<aop:config>
    <!--    设置切面 这里这个ref就是我们要把那个类切入    -->
    <aop:aspect ref="diy">
        <!--       切入点     -->
        <aop:pointcut id="point" expression="execution(*com.xue.service.UserServiceImpl.*(..))"/>
        <aop:before method="before" pointcut-ref="point"/>
        <aop:after method="after" pointcut-ref="point"/>
    </aop:aspect>
public class DiyPointCut {
    public void before() {
        System.out.println("===========before============");
    }

    public void after() {
        System.out.println("==========after=============");

    }
}

11 整合Mybtis

环境配置

jar包

mybatis

mysql

spring

aop

mybatis-spring

方法

Mybatis-Spring 方法一

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

关于Spring来接管MyBatis

Mybatis原有的数据源将会被接管

只需要 建立一个 Mybatis-dao.xml 随后将xml引入到 完整的xml中即可

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

    <aop:aspectj-autoproxy/>
    <context:annotation-config/>

    <!--   指定要扫描的包 -->
    <context:component-scan base-package="com.xue"/>

    <!--  DataSource : 使用Spring Mybatis来替换  -->
    <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;characterEncoding=UTF-8"/>
        <property name="username" value="root"/>
        <property name="password" value="1111"/>
    </bean>
    <!--  sql Session  -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!--    绑定Mybatis配置文件    -->
        <property name="configLocation" value="mybatis-config.xml"/>
    </bean>

    <!--   sqlSession  -->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>


</beans>

这样就可以完成连接的建立这个过程并且完成了之前的获取sqlsession这个工具类的步骤,利用的是SqlSessionTemplate来实现

接下来来个测试!

假如说存在Teahcer 表在数据库中

我们要获取表的数据

在MyBatis中

  1. 创建pojo
  2. 做一个mapper的接口与实现它的xml文件
  3. 利用工具类来获取sqlsession,随后获取 xml所实现的方法,然后再使用方法,来获取数据

(具体代码不再赘述)

在MyBatis-Spring中不同,因为工具类获取sqlsession已经被Spring给接管了,我们可以尝试做一个AOP(我理解的叫AOP)来进行操作

即我们不用xml来实现单一的实现接口而改用一个类来实现接口,随后再用这个类来实现xml文件,我们只需要把我们到的sqlsession注入到这个类中,就可以了。像下面这样:

<bean id="teacherMapper" class="com.xue.mapper.TeacherMapperImpl">
    <property name="sqlSession" ref="sqlSession"/>
</bean>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IbPEVOJK-1620977292089)(…/…/未命名文件(2)].png)

然后它的impl可以是

public class TeacherMapperImpl implements TeacherMapper{
    //设置一下将要注入的session

    private SqlSessionTemplate sqlSession;

    public SqlSessionTemplate getSqlSession() {
        return sqlSession;
    }
    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }
    @Override
    public List<Teacher> queryTeacher() {
        //获取要操作的Mapper
        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);

        //这个时候 这个mapper已经是实现了TeacherMapper.xml 这个文件里的方法
        return  mapper.queryTeacher();


    }
}

测试类可以是:

public class MyTest {
    public static void main(String[] args) throws IOException {


        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        TeacherMapper userMapper = (TeacherMapper) context.getBean("teacherMapper");


        List<Teacher> queryUser = userMapper.queryTeacher();
        queryUser.forEach(System.out::println);
    }
}

Mybatis-Spring 方法二

终极简化版本

SqlSessionDaoSupport

SqlSessionDaoSupport 是一个抽象的支持类,用来为你提供 SqlSession。调用 getSqlSession() 方法你会得到一个 SqlSessionTemplate,之后可以用于执行 SQL 方法,就像下面这样:

public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
  public User getUser(String userId) {
    return getSqlSession().selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);
  }
}

在这个类里面,通常更倾向于使用 MapperFactoryBean,因为它不需要额外的代码。但是,如果你需要在 DAO 中做其它非 MyBatis 的工作或需要一个非抽象的实现类,那么这个类就很有用了。

SqlSessionDaoSupport 需要通过属性设置一个 sqlSessionFactorySqlSessionTemplate。如果两个属性都被设置了,那么 SqlSessionFactory 将被忽略。

假设类 UserMapperImplSqlSessionDaoSupport 的子类,可以编写如下的 Spring 配置来执行设置:

<bean id="userDao" class="org.mybatis.spring.sample.dao.UserDaoImpl">
  <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

这是一个化简的方法

这样的话我们可以省去sqlsession注入SqlSessionTemplate这个过程

12 事务

  • 原子性
  • 隔离性
  • 一致性
  • 持久性

要开启 Spring 的事务处理功能,在 Spring 的配置文件中创建一个 DataSourceTransactionManager 对象:

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <constructor-arg ref="dataSource" />
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <constructor-arg ref="dataSource"/>
</bean>

<!--    设置切入点   -->
<!--    配置事务通知  -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!--        给那些方法配置事务     propagation 事务的属性 -->
    <tx:attributes>
        <tx:method name="add" propagation="REQUIRED"/>
        <tx:method name="*"/>
    </tx:attributes>
</tx:advice>

<!--    配置事务的切入     -->
<aop:config>
    <aop:pointcut id="txPointcut" expression="(execution(* com.xue.mapper.*(..)))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"></aop:advisor>
</aop:config>
 配置来执行设置:

```

这是一个化简的方法

这样的话我们可以省去sqlsession注入SqlSessionTemplate这个过程

12 事务

  • 原子性
  • 隔离性
  • 一致性
  • 持久性

要开启 Spring 的事务处理功能,在 Spring 的配置文件中创建一个 DataSourceTransactionManager 对象:

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <constructor-arg ref="dataSource" />
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <constructor-arg ref="dataSource"/>
</bean>

<!--    设置切入点   -->
<!--    配置事务通知  -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!--        给那些方法配置事务     propagation 事务的属性 -->
    <tx:attributes>
        <tx:method name="add" propagation="REQUIRED"/>
        <tx:method name="*"/>
    </tx:attributes>
</tx:advice>

<!--    配置事务的切入     -->
<aop:config>
    <aop:pointcut id="txPointcut" expression="(execution(* com.xue.mapper.*(..)))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"></aop:advisor>
</aop:config>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值