初入Spring 完整的Spring介绍

1、Spring

1.1、简介

Spring框架是由于软件开发的复杂性而创建的。

  • 目的:解决企业应用开发的复杂性

  • 功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能

  • 范围:任何Java应用

  • Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。

  • 2002年,首次推出Spring框架雏形:interface 21框架

  • Spring框架即以interface21框架为基础,经过重新设计,并不断丰富其内涵,于2004年3月24日,发布了1.0正式版。

  • Rod Johnson Spring Framework创始人,著名作者。 Rod在悉尼大学不仅获得了计算机学位,同时还获得了音乐学位。更令人吃惊的是在回到软件开发领域之前,他还获得了音乐学的博士学位。 有着相当丰富的C/C++技术背景的Rod早在1996年就开始了对Java服务器端技术的研究。

  • SSH:Strutc2+Spring+Hibernate!

  • SSM:SpringMVC+Spring+Mybatis

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

1.2、优点

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

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

1.3、组成

1.4、扩展

  • Spring Boot

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

    • SpringCloud是基于SpringBoot实现的

2、IOC理论推导

private UserDao userDao;
//利用set注入进行动态实现值的注入
public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
  • 之前,程序是主动创建对象!控制权在程序员手里
  • 利用set注入之后,程序不再有主动性控制器在用户手里

本质上解决了问题,我们再也不用去管创建对象。系统的耦合大大降低了,这就是IOC的原型

IOC的本质

控制反转IOC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IOC的一种方法

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

配置文件

<?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">

</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">

<!--    使用Spring来创建对象,在Spring都称为Bean-->
<!--    //使用Spring来创建对象,在Spring中都称为Bean
        //类型 变量名=new 类型();
        //Hello hello = new Hello()
        // id =变量名
        //class= new 对象
        //
-->
    <bean id="hello" class="com.bing.pojo.Hello" >
        <property name="str" value="Hello,Spring"/>
    </bean>

</beans>
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());
    }

3、HelloSpring

先创建一个对象

public class Hello {

    private String str;

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }

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

然后在Spring配置文章中注册

 <bean id="hello" class="com.bing.pojo.Hello" >
        <property name="str" value="Hello,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());
    }

结果

4、IOC创建对象的方式

三种方式

    <bean id="user" class="com.bing.pojo.User">
        <!--    下标赋值-->
        <!--        <constructor-arg index="0" value="helliSpring"/>-->
        <!--   根据类型赋值     -->
        <!--        <constructor-arg type="java.lang.String" value="HELLOSPRING"/>-->
        <!--        通过参数名赋值-->
        <constructor-arg name="name" value="helloSPring"/>
    </bean>

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

测试创建两个对象

public class User {


    private String name;

    public User(String name) {
        this.name = name;
    }


    public User() {
        System.out.println("无参构造!");
    }

    public String getName() {
        return name;
    }

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

    public void show() {
        System.out.println("name=" + name);
    }
}

public class UserT {


    private String name;


    public UserT() {
        System.out.println("UserT无参构造!");
    }

    public String getName() {
        return name;
    }

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

    public void show() {
        System.out.println("name=" + name);
    }
}

在配置文件中注册

 <bean id="user" class="com.bing.pojo.User">
        <constructor-arg name="name" value="helloSPring"/>
    </bean>
    <bean id="userT" class="com.bing.pojo.UserT">
    </bean>

测试代码

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

    }

结果

从而得出,在Spring配置文件中,注册之后,就会初始化完成。

5、Spring配置

5.1、别名

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

5.2、Bean配置

<!--    id :Bean的唯一标识符,也就是想当于我们学的对象名
class:Bean对象所对应的全限定名:包名+类型
name:也是别名,而且name可以取多个别名
-->
<bean id="userT" class="com.bing.pojo.UserT" name="t,t1">
</bean>

5.3、import

我们可以不同的Bean.xml文件导入的一个总的applicationContext.xml

<import resource="beans.xml"/>

Bean.xml文件中如果和其他的文件存在相同的,不会发生冲突

6、依赖注入

6.1、构造器注入

前面已经有笔记了

6.2、set注入

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

【环境搭建】

编写Student

public class Student {

    private String name;
    private Address address;
    private String[] books;
    private List<String > hobbys;
    private Map<String,String> card;
    private Set<String> games;
    private String wife;
    private Properties info;
}

编写Address

public class Address {
    private String address;
}

配置beans.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">


    <bean id="address" class="com.bing.pojo.Address">
        <property name="address" value="北京"/>
    </bean>


    <bean id="student" class="com.bing.pojo.Student">
        <!--        第一种普通值注入,直接使用Value-->
        <property name="name" value="北五"/>
        <!--        第二种Bean注入 ref-->
        <property name="address" ref="address"/>
        <!--数组注入-->
        <property name="books">
            <array>
                <value>西游记</value>
                <value>三国演义</value>
                <value>红楼梦</value>
            </array>
        </property>
        <property name="hobbys">
            <list>
                <value>打游戏</value>
                <value>看动画</value>
            </list>
        </property>
        <property name="card">
            <map>
                <entry key="007" value="大话西游"/>
                <entry key="电话" value="110119120111"/>
            </map>
        </property>
        <property name="games">
            <set>
                <value>王者荣耀</value>
                <value>绝地求生</value>
                <value>英雄归来</value>
            </set>
        </property>
        <property name="wife">
            <null/>
        </property>
        <property name="info">
            <props>
                <prop key="邮箱">110@163.com</prop>
                <prop key="学号">202100001</prop>
            </props>
        </property>
    </bean>

</beans>

编写测试类

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.toString());
    }
}

6.3拓展注入

要使用c命名空间和b命名空间

首先导入

xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
<!--    set注入-->
<bean id="user" class="com.bing.pojo.User" p:age="19" p:name="北五"/>
<!--    构造器注入  必须要有构造器-->
<bean id="user1" class="com.bing.pojo.User" c:age="10" c:name="北五五"/>

6.4、Bean的作用域

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

    1.  <bean id="user1" class="com.bing.pojo.User" c:age="10" c:name="北五五" scope="singleton"/>
      
  2. 原型模式:每次从容器种get的时候,都会产生一个新对象

    1. <bean id="user1" class="com.bing.pojo.User" c:age="10" c:name="北五五" scope="prototype"/>
      
  3. 其余的request、session、application,这些只有在web开发中使用

7、Bean的自动装配

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

在Spring中有三种装配方式

  1. 在xml中显示的配置
  2. 在java中显示配置
  3. 隐式的自动装配Bean

7.1、测试

【环境搭建】:一个有两个宠物

7.2、BYName自动装配


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

<!--    byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的BeanId!

    -->
<bean id="people" class="com.bing.pojo.People" autowire="byName">
    <property name="name" value="北五"/>
</bean>

7.3、ByType自动装配

<bean class="com.bing.pojo.Cat"/>
<bean class="com.bing.pojo.Dog"/>

<!--   
        byType:会自动在容器上下文查找,和自己对象属性相同类型的Bean!
-->
<bean id="people" class="com.bing.pojo.People" autowire="byType">
    <property name="name" value="北五"/>
</bean>

小结:

  1. 使用byname的时候,需要保证所有的bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致
  2. 使用bytype的时候,需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性类型一致!

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

JDK1.5支持的注解,Spring2.5就支持注解开发

要使用注解

  1. 导入约束

    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">
    
  2. 配置注解支持 context:annotation-config/开启支持 可以忽略set方法

    <?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>
    

@Autowird

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

使用Autowird我们可以不用编写set方法,但是必须要这个自动装配的属性在IOC(spring)容器中存在。实际还是Byname

测试

public class People {

    @Autowired
    private Dog dog;
    @Autowired
    private Cat cat;

    private String name;
}

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

public class People {

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

    private String name;
}
<bean id="cat" class="com.bing.pojo.Cat"/>
<bean id="cat123" class="com.bing.pojo.Cat"/>

8、使用注解开发

在Spring4之后,要使用注解开发,必须导入AOP的包

  1. bean

    1. @Resource:自动装配 通过名字和类型
      
    2. @Component:组件,放在类上,说明这个类被Spring管理了
      
  2. 属性如何注入

    1. //组件
      @Component
      public class User {
      
          public String name;
          
          @Value("北五")   //相当于 <property name="name" value="北五"/>
          public void setName(String name) {
              this.name = name;
          }
      }
      
  3. 衍生的注解

    1. @Component有几个衍生注解,我们在web开发中,会按照MVC三层架构分层
      1. dao ---【@ResponseBody】习惯用这个标识
      2. service----【@Service】习惯用这个标识
      3. controller----【@Controller】习惯用这个标识
      4. 以上四个注解的功能都是一样的,都是代表将某个类注册到Spring中,装配到bean
  4. 自动装配

    @Resource:自动装配 通过名字和类型

    @Component:组件,放在类上,说明这个类被Spring管理了

  5. 作用域

    @Component
    @Scope("singleton")
    public class User {
    
        public String name;
    
        @Value("北五")   //相当于 <property name="name" value="北五"/>
        public void setName(String name) {
            this.name = name;
        }
    }
    
  6. 小结

    XML与注解

    • xml更万能,适用于任何场景!维护简单
    • 注解不是自己的类使用不了,维护复杂

    xml与注解最佳事件

    • ​ xml用来管理bean
    • 注解只负责完成属性的注入
    • 我们在使用的过程中,只需要注意一个问题:必须开启注解支持

9、使用java的方式配置Spring

我们现在要完全不使用Spring的xml配置,全权交给java来做!

javaConfig是Spring的子项目,在Spring4之后它成为了核心功能

编写实体类

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

@Controller
public class User {

    private String name;

    public String getName() {
        return name;
    }
    @Value("北五")
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}
@Configuration
@ComponentScan("com.bing.pojo")
@Import(BingConfig1.class)
public class BingConfig {
    //注册一个Bean就相当于我们之前xml写的bean标签
    //这个方法的名字就相当于bean标签中的id
    //这个返回值就相当于bean标签中的class
    @Bean
    public User getUser() {
        return new User();
    }
}

public class MyTest {
    public static void main(String[] args) {
        //如果完全使用配置类方式去做,我们就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载
        ApplicationContext context = new AnnotationConfigApplicationContext(BingConfig.class);
        User getUser = (User) context.getBean("getUser");
        System.out.println(getUser.toString());
    }
}

10、代理模式

为什么要学代理模式呢?

因为这就是SpringAOP的底层!【SpringAOP和SpringMVA】

代理模式:

  • 静态代理
  • 动态代理

10.1、静态代理

角色分析:

  • 抽象角色:一般会使用接口或者抽象类来解决

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

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

  • 客户:访问代理对象的人

代理模式的好处:

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

缺点:

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

10.2、动态代理

  • 动态代理和静态代理角色一样
  • 动态代理的类是动态生成的,不是我们直接写好的
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
    • 基于接口最经典的是JDK动态代理【这里使用的就在基于接口的】
    • 基于类的动态代理 cglib
    • Java字节码

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

编写一个接口

public interface UserService {

    public void add();

    public void delete();

    public void update();

    public void query();
}

实现接口

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("查询了数据库");
    }
}

编写动态代理

public class ProxyIn implements InvocationHandler {

    private Object target;

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

    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 {
        log(method.getName());
        Object invoke = method.invoke(target, args);
        return invoke;
    }

    public void log(String msg) {
        System.out.println("执行了" + msg + "方法");
    }
}

测试

public static void main(String[] args) {
    UserServiceImpl userService = new UserServiceImpl();

    ProxyIn proxyIn = new ProxyIn();

    proxyIn.setUserService(userService);

    UserService proxy = (UserService) proxyIn.getProxy();
    proxy.add();
}

动态代理的好处:

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

11、AOP

11.1、什么是AOP

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

11.2、使用Spring实现AOP

需要导入织入包

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>

方式一:使用Spring的API接口

<?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="userService" class="com.bing.service.UserServiceImpl"/>
    <bean id="log" class="com.bing.log.Log"/>
    <bean id="alog" class="com.bing.log.Alog"/>

    <!--    方式一:使用原生SpringAPi接口-->
    <!--    配置aop-->
    <aop:config>
        <!--    需要切入点 expression:表达式 -->
        <aop:pointcut id="pointcut" expression="execution(* com.bing.service.UserServiceImpl.*(..))"/>
        <!--        执行环绕增加-->
                <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
                <aop:advisor advice-ref="alog" pointcut-ref="pointcut"/>
    </aop:config>

</beans>

编写接口

public interface UserService {
    public void add();

    public void delete();

    public void update();

    public void query();
}

实现接口

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 Log implements MethodBeforeAdvice {

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

添加日志2

public class Alog implements AfterReturningAdvice {

    //o:返回值
    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("执行了:" + method.getName() + "方法," + "返回结果为:" + o);
    }
}

执行结果

注意点:需要导入包!!!!!

方式二:自定义类实现AOP

配置xml

  <!--    方式二:自定义类-->
    <bean id="diy" class="com.bing.diy.DiyPointCut"/>

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

        </aop:aspect>
    </aop:config>

自定义类

public class DiyPointCut {

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

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

执行结果

方式三:使用注解实现

 <!--方式三-->
    <bean id="annotationPointCut" class="com.bing.diy.AnnotationPointCut"/>
    <!--开启注解支持-->
    <aop:aspectj-autoproxy/>

编写自定义类

@Aspect //标注这个类是一个切面
public class AnnotationPointCut {
    @Before("execution(* com.bing.service.UserServiceImpl.*(..))")
    public void before() {
        System.out.println("===========方法执行前=========");
    }

    @After("execution(* com.bing.service.UserServiceImpl.*(..))")
    public void after() {
        System.out.println("============方法执行后========");
    }

    @Around("execution(* com.bing.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("环绕前");
        Signature signature = point.getSignature();
        Object proceed = point.proceed();
        System.out.println(signature);
        System.out.println("环绕后");
    }
}

结果

12、整合Mybatis

步骤:

  1. 导入相关的jar包

    • junit

    • mybatis

    • mysql数据库

    • spring相关

    • aop织入

    • mybatis-spring【new】

      <dependencies>
          <dependency>
              <groupId>mysql</groupId>
              <artifactId>mysql-connector-java</artifactId>
              <version>5.1.49</version>
          </dependency>
          <dependency>
              <groupId>org.mybatis</groupId>
              <artifactId>mybatis</artifactId>
              <version>3.5.6</version>
          </dependency>
          <dependency>
              <groupId>junit</groupId>
              <artifactId>junit</artifactId>
              <version>4.13</version>
          </dependency>
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-jdbc</artifactId>
              <version>5.3.4</version>
          </dependency>
          <dependency>
              <groupId>org.aspectj</groupId>
              <artifactId>aspectjweaver</artifactId>
              <version>1.9.4</version>
          </dependency>
          <dependency>
              <groupId>org.mybatis</groupId>
              <artifactId>mybatis-spring</artifactId>
              <version>2.0.2</version>
          </dependency>
      </dependencies>
      
  2. 编写配置文件

  3. 测试

12.1、回忆mybatis

  1. 编写实体类

    @Data
    public class User {
    
        private int id;
        private String name;
        private String pwd;
    }
    
  2. 编写核心配置文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <!--核心配置文件-->
    <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=true&amp;useUnicode=true&amp;characterEncoding=utf-8"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                </dataSource>
            </environment>
        </environments>
        <mappers>
            <mapper resource="com/bing/dao/UserMapper.xml"/>
        </mappers>
    </configuration>
    
  3. 编写接口

    public interface UserMapper {
        List<User> getUser();
    }
    
  4. 编写Mapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <!--namespace=绑定一个对应的Mapper接口-->
    <mapper namespace="com.bing.dao.UserMapper">
        <!--   select查询语句 -->
        <select id="getUser" resultType="com.bing.pojo.User">
            select *
            from mybatis.user
        </select>
    </mapper>
    
  5. 测试

    public static void main(String[] args) throws IOException {
        String resources = "mybatis-config.xml";
        InputStream resource = Resources.getResourceAsStream(resources);
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(resource);
        SqlSession sqlSession = sessionFactory.openSession(true);
    
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> user = mapper.getUser();
        for (User user1 : user) {
            System.out.println(user1);
        }
        sqlSession.close();
    }
    

总结:

  1. 需要将IDEA的默认语言设置为UFT-8否则可能会出现意想不到的错

  2. 资源过滤需要开启

    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
    
  3. resultType返回的类型需要写全限定名,否则也可能会出现错误,文件尽量写权限名,避免错误,虽然很多。。

12.2、mybatis-Spring

方式一:

  1. 编写数据源

    <!--  datasource:使用Spring的数据源替换mybatis的配置 c3p0 dbcp druid
    这里我们使用Spring提供的JDBC:org.springframework.jdbc.datasource
      -->
    <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=true&amp;useUnicode=true&amp;characterEncoding=utf-8"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>
    
  2. sqlSessionFactory

    <!--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/bing/dao/*.xml"/>
    </bean>
    
  3. SqlSessionTemplate

    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--只能使用构造器注入sqlSessionFactory 因为没有set方法-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>
    
  4. UserMapperImpl

    public class UserMapperImpl implements UserMapper {
    
        //我们所有的操作,以前都是用sqlSession来执行,,现在我们使用SqlSessionTemplate
    
        private SqlSessionTemplate sqlSession;
    
        public void setSqlSession(SqlSessionTemplate sqlSession) {
            this.sqlSession = sqlSession;
        }
    
        @Override
        public List<User> selectUser() {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            return mapper.selectUser();
        }
    }
    
  5. 测试

    <bean id="userMapper" class="com.bing.dao.UserMapperImpl">
        <property name="sqlSession" ref="sqlSession"/>
    </bean>
    
    public static void main(String[] args) throws IOException {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
        List<User> userList = userMapper.selectUser();
        for (User user : userList) {
            System.out.println(user);
        }
    }
    

小结:总体而言把mybatis-config.xml的部分配置文件编写到了spring-dao.xml,但是真的配置繁琐,以前我们需要手动获取sqlSessionFactory,现在我们直接只用SqlSessionTemplate来自动注入。

方式二:更改以上部分代码

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper {

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

添加Bean

<bean id="userMapper2" class="com.bing.dao.UserMapperImpl2">
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

测试

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

13、声明式事务

1、回顾事务

  • 要么都成功,要么都失败
  • 事务在项目开发中,十分重要,涉及到数据一致性的问题
  • 确保完整性和一致性

事务ACID原则

  • 原子性
  • 一致性
  • 隔离性
    • 多个业务同事操作同一个资源,防止数据损坏
  • 持久性

2、Spring中的事务管理

  • 声明式事务:AOP
  • 编程式事务:需要更改源码

织入

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

    <!--结合AOP进行事务织入-->
    <!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--给哪些方法配置事务-->
        <!--配置事务的传播信息 new    propagation默认的是REQUIRED-->
        <tx:attributes>
            <tx:method name="add" propagation="REQUIRED"/>
            <tx:method name="delete" propagation="REQUIRED"/>
            <tx:method name="update" propagation="REQUIRED"/>
            <tx:method name="query" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

    <!--事务的切入-->
    <aop:config>
        <aop:pointcut id="txPointCut" expression="execution(* com.bing.mapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>

不更改源码的情况下,建议使用织入

为什么需要事务?

  • 如果不配置事务,数据的安全性,一致性,同步性得不到保障
  • 如果我们不在Spring中去配置事务,我们就需要在代码中手动配置
  • 事务在项目的开发中十分重要,涉及到数据的一致性和完整性问题

学习是快乐的

posted @ 2021-03-07 23:07  大格子  阅读(108)  评论(0)    收藏  举报