Spring_刘锋的博客

一、Spring

简介

https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop-api 官方文档

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

2002年,首次推出雏形interface21框架

2004年首次发布1.0版本

Spring的初衷:

1、JAVA EE开发应该更加简单。

2、使用接口而不是使用类,是更好的编程习惯。Spring将使用接口的复杂度几乎降低到了零。

3、为JavaBean提供了一个更好的应用配置框架。

4、更多地强调面向对象的设计,而不是现行的技术如JAVA EE。

5、尽量减少不必要的异常捕捉。

6、使应用程序更加容易测试。

Spring的目标:

1、可以令人方便愉快的使用Spring。

2、应用程序代码并不依赖于Spring APIs。

3、Spring不和现有的解决方案竞争,而是致力于将它们融合在一起。

Spring的基本组成:

1、最完善的轻量级核心框架。

2、通用的事务管理抽象层。

3、JDBC抽象层。

4、集成了Toplink, Hibernate, JDO, and iBATIS SQL Maps。

5、AOP功能。

6、灵活的MVC Web应用框架。

maven配置

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

优点

是一个开源免费的框架(容器)

是一个轻量级的、非入侵式的框架

控制反转(IOC),面向切面编程(AOP)

支持事务的处理,对框架整合的支持

组成

img

拓展

Spring Boot

一个快速开发的脚手架

基于SpringBoot可以快速的开发单个的微服务

约定大于配置

Spring Cloud

基于SpringBoot实现的,相当于微服务的整合

因为现在大多数的公司都在使用springBoot来开发,学习SpringBoot的前提是完全掌握Spring和SpringMVC

Spring弊端:发展了太久之后,违背了原来的理念,配置十分繁琐,人称“配置地狱”

二、IOC理论推导

https://blog.csdn.net/qq_33369905/article/details/106647330

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

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

我们使用set接口注入,已经发生了革命性的变化

public class UserServiceImpl implements UserService {
    private UserDao userDao ;

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

    public void getUserService() {
        userDao.getUser();
    }
}

之前程序是主动的创建对象,主动权再程序员的手上

使用了set注入以后,程序不在具有主动性,而是变成了被动的接受

这种思想,从本质上解决了问题,程序员不需要再主动的管理对象的创建。系统的耦合性大大降低,可更加专注的在业务的实现上,这是IOC的原型(控制反转

helloSpring

在这里插入图片描述

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-3.2.xsd">
    <!-- 由 Spring容器创建该类的实例对象 -->
    <bean id="hello" class="domain.Hello">
        <property name="str" value="spring hello"/>
    </bean>
</beans>

Hello.class

public class Hello {
    private String str;

    public String getStr() {
        return str;
    }

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

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

MyTest.class

public class MyTest {
    public static void main(String[] args) {
        // 获取spring的上下文
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        // 我们的对象都在spring中管理了,只用就直接从里面取出来就可以
        Hello hello = (Hello) context.getBean("hello");
        System.out.println(hello.getStr());

    }
}

dao的spring托管配置

<!-- 由 Spring容器创建该类的实例对象 -->
<bean id="userDaoImpl" class="dao.UserDaoImpl"/>
<bean id="userDaoMysqlImpl" class="dao.UserDaoMysqlImpl"/>

<bean id="service" class="services.UserServiceImpl" >
    <property name="userDao" ref="userDaoImpl"/>
</bean>

三、IoC创建对象的方式

无参

使用 无参构造创建对象,就是默认实现

<!--无参构造-->
<bean id="user" class="pojo.User">
    <property name="name" value="刘锋"/>
</bean>
public User() {    System.out.println("user的无参构造");}
/*无参构造创建对象 */  ApplicationContext context = 
new ClassPathXmlApplicationContext("beans.xml");  
User user = (User) context.getBean("user");  
System.out.println(user.toString());

有参

使用有参构造创建对象,在使用有参构造的时候,xml配置文件如果有无参构造的配置,那么程序会先调用无参构造的函数生成一个对象,再使用有参的构造

1.下标赋值,下标index是构造函数形参的位置

<!--有参构造-->
<bean id="userIndex" class="pojo.User">   
 <constructor-arg index="0" value="贾晨霞"/>
 </bean>

2.类型赋值,类型是形参的类型(不推荐使用)

<bean id="userString" class="pojo.User">    
<constructor-arg type="java.lang.String" value="贾可爱"/>
</bean>

3.使用参数的名字来创建

<bean id="userName" class="pojo.User">    
<constructor-arg name="name" value="溜溜溜"/>
</bean>

总结:一个存在无参构造函数的类,在配置文件配置无参类加载的时候,容器中管理的对象就已经初始化了,每一个对象都是同一个对象,单例的

四、Spring配置

别名

<!--别名--><alias name="user" alias="useruser"/>

如果添加了别名,也可以通过别名来获取到对象

bean的配置

<bean id="bean的唯一标识符" 
class="bean的全限定名,bean对象对应的全限定名"       
name="id的别名,而且那么可以同时起多个别名,中间用逗号或者空格等好多的分隔符来分隔"        
scope="选择模式(单例、原型等)">    
</bean>

import

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

假设现在项目中有多个人开发,负责不同的类来开发,需要注册在不同的bean.xml中,我们可以中的import将所有的bean合并称为一个,这样就可以使用同一个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-3.2.xsd">    
<import resource="beans.xml"/>    
<import resource="beans2.xml"/>    
<import resource="beans3.xml"/>
</beans>

五、DI依赖注入

构造器注入

上文所说的就是构造器注入

set方式注入(重点)

依赖注入的本质就是set注入

分为两个部分,依赖就是bean对象的创建依赖于容器,注入就是bean对象的所有属性就是由容器来注入。

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

<bean id="student" class="pojo.Student">
    <!--第一种普通值注入-->
    <property name="name" value="刘锋"/>
    <!--bean注入-->
    <property name="address" ref="address"/>
    <!--数组-->
    <property name="books">
        <array>
            <value>红楼梦</value>
            <value>水浒传</value>
            <value>三国演义</value>
            <value>西游记</value>
        </array>
    </property>
    <!--list集合-->
    <property name="hobbys">
        <list>
            <value>打游戏</value>
            <value>看java</value>
            <value>唱歌</value>
        </list>
    </property>
    <!--map集合-->
    <property name="card">
        <map>
            <entry key="学生证" value="789132113"/>
            <entry key="身份证" value="1329456897851"/>
            <entry key="水卡" value="1213123"/>
        </map>
    </property>
    <!--set集合-->
    <property name="games">
        <set>
            <value>LOL</value>
            <value>CF</value>
        </set>
    </property>
    <!--null-->
    <property name="wife">
        <null/>
    </property>
    <!--properties-->
    <property name="info">
        <props>
            <prop key="driver">2202020</prop>
            <prop key="url"></prop>
            <prop key="password">123456</prop>
            <prop key="username">贾晨霞</prop>
        </props>
    </property>
</bean>

其他拓展方式注入

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

    <!--p:property 可以直接注入属性的值-->
    <bean id="user" class="pojo.User" p:name="刘锋" p:age="20"/>

</beans>

c命名空间注入

xmlns:c="http://www.springframework.org/schema/c"
<!--c:construct 通过构造器注入-->
<bean id="user" class="pojo.User" c:age="18" c:name="贾晨霞"/>

bean的作用域

在这里插入图片描述

单例模式(默认的模式)

<bean id="user" class="pojo.User" c:age="18" c:name="贾晨霞" scope="singleton"/>

在这里插入图片描述

原型模式,每次getBean都是一个新的对象

 <bean id="user" class="pojo.User" c:age="18" c:name="贾晨霞" scope="prototype"/>

其余的在web开发中使用

六、bean的自动装配

自动装配是spring满足bean依赖的一种方式

Spring会上下文自动查找,并且给bean自动装配属性

在spring中,有三种装配的方式

1、在xml中显示的配置

2、在java中显示的配置

3、隐式 的自动装配bean(重要)

测试

环境搭建

一个人有两个宠物

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

    public People() {
    }

    public People(Cat cat, Dog dog, String name) {
        this.cat = cat;
        this.dog = dog;
        this.name = name;
    }

    public Cat getCat() {
        return cat;
    }

    public People setCat(Cat cat) {
        this.cat = cat;
        return this;
    }

    public Dog getDog() {
        return dog;
    }

    public People setDog(Dog dog) {
        this.dog = dog;
        return this;
    }

    public String getName() {
        return name;
    }

    public People setName(String name) {
        this.name = name;
        return this;
    }
    @Override
    public String toString() {
        return "People{" +
                "cat=" + cat +
                ", dog=" + dog +
                ", name='" + name + '\'' +
                '}';
    }
}

自动装配

ByName

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

<!--
ByName会自动查找和自己对象set方法后面的值对应的beanid
-->
<bean id="people" class="pojo.People" autowire="byName">
    <property name="name" value="刘锋"/>
</bean>

在这里插入图片描述

在这里插入图片描述

ByType

<!--
byType  会查找和自己对象属性类型相同的bean
-->
<bean id="people" class="pojo.People" autowire="byType">
    <property name="name" value="贾晨霞"/>
</bean>

小结:

但是上述的两个都有弊端,名字或者类型必须是全局唯一的且和pojo类的属性的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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
</beans>

配置注解支持

<context:annotation-config/>

@Autowired

在pojo类的想要自动装配的属性的前面添加这个注解(就可以不用去写属性的set方法)

也可以在set方法上写

public class People {
    @Autowired
    private Cat cat;
    @Autowired
    private Dog dog;
    private String name;
}
//    如果显示的设置了required属性的值为false,则这个属性可以为null,不会有空指针异常,否则不能为null
    @Autowired(required = false)
    private Cat cat;

自动装配的对象存在多个对象,可以指定唯一的一个bean对象

@Autowired
@Qualifier(value = "dog1111")
private Dog dog;
<bean id="cat" class="pojo.Cat"/>
<bean id="dog" class="pojo.Dog"/>
<bean id="dog1111" class="pojo.Dog"/>

@Resource

@Resource
private Cat cat;
  1. 都是自动装配的,可以放在属性字段上
  2. @Autowired的默认是根据属性的类型来匹配的
  3. @Resource的默认是先根据名字来查找,找不到以后再按类型来查找

七、Spring 使用注解开发

首先要导入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:component-scan base-package="pojo"/>
        <context:annotation-config/>
    
    </beans>
    
  2. 属性如何注入

    //等价于<bean id="user" class="pojo.User"/>@Componentpublic class User {    @Value("刘锋")    private String name;
    
  3. 衍生的注解

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

    dao

    @Repositorypublic class UserDao {}
    

    service

    @Servicepublic class UserService {}
    

    controller

    @Controller
    public class UserController {
    }
    

    这四个注解的功能是一样的,都是将某个类注册到Spring容器中

  4. 自动装配

    @Autowired的默认是根据属性的类型来匹配的

    @Resource的默认是先根据名字来查找,找不到以后再按类型来查找

  5. 作用域

    @Component
    @Scope("singleton")
    public class User {
        @Value("刘锋")
        private String name;
    }
    
    
  6. 小结

xml与注解

xml更加万能适用于更多场合,维护简单方便

注解不是自己的类使用不了,维护相对复杂

xml和注解的最佳实践:

xml来管理bean

注解只是用来负责完成属性的注入

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

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

八、完全使用java的方式配置Spring

我们现在要完全不适用xml来配置,全权交给java

JavaConfig是Spring的一个子项目,但是在Spring4之后成为了一个核心的功能

pojo类

// 这个注解的意思,就是这个类Spring接管了,注册到了容器中@Componentpublic class User {    private String name;    public String getName() {        return name;    }    //属性注入值    @Value("刘锋")    public User setName(String name) {        this.name = name;        return this;    }}

MyConfig配置类

这是一个配置类,就和beans.xml一样的

@Configuration // 代表它是一个配置类@ComponentScan("pojo") // 扫描包@Import(MyConfig2.class) // 引入别的配置类public class MyConfig {    // 注册一个bean,就是之前写的一个bean标签  id就是这个方法的名字,返回值就是class属性    @Bean    public User getUser() {        return new User(); // 就是返回要注入到bean的对象    }}

测试类

public class MyTest {
    public static void main(String[] args) {
        // 如果完全使用了java类的配置方式以后,我们就只能使用AnnotationConfigApplicationContext来获取上下文容器,通过配置类的class对象加载
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        User user = (User) context.getBean("getUser");

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

这种纯Java配置,在SpringBoot中随处可见

九、代理模式

中介

为什么要学习代理模式

因为这就是SpringAOP的底层,SpringAOP和SpringMVC

代理模式的分类

静态代理

动态代理

在这里插入图片描述

静态代理

角色分析

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

真实角色:被代理的角色

代理角色:代理真实角色,代理真实角色后,我们一般会进行一些附属的操作

客户:访问代理角色的人

代理模式的好处

可以使真实角色的操作更加纯粹,不用去关注一些公共的业务

公共业务就交给代理角色,实现了业务的分工

公共业务发生扩展的时候,方便集中管理

缺点:

一个真实对象就会产生一个代理对象,会使代码量翻倍

加深理解

动态代理

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

动态代理的代理类是动态生成的,不是我们直接写好的

动态代理也分为两大类

基于接口的动态代理:JDK的动态代理

基于类的动态代理

java字节码实现:JAVAsist

两个类:Proxy(得到代理类)、InvocationHandler(调用处理程序)

public class ProxyHost implements InvocationHandler {
    /**
     * 被代理的接口
     */
    private IHourse hourse;

    public ProxyHost setHourse(IHourse hourse) {
        this.hourse = hourse;
        return this;
    }

    /**
     * 得到代理类
     *
     * @return
     */
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), hourse.getClass().getInterfaces(), this);
    }

    // 处理代理实例,并且返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 动态代理的本质就是使用反射机制
        Object result = method.invoke(hourse, args);

        return result;
    }
}

一个动态代理类实现的是一个接口,对应的是一类业务

十、AOP

什么是AOP

面向切面编程

AOP在Spring中的作用

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

横切关注点:跨越应用程序多个模块的方法或者功能

切面:横切关注点被模块化的特殊对象,就是一个类

通知:切面必须完成的工作,就是类中的一个方法

目标:被通知的对象

代理:向目标对象应用通知之后创建的对象

切入点:切面通知执行的地点的定义

连接点:与切入点匹配的执行点

在这里插入图片描述

AOP实现

添加依赖

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

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

</beans>

方式一:使用Spring的API接口

service接口

public interface UserService {
    void add();

    void delete();

    void update();

    void select();
}

service实现类

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

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

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

    public void select() {
        System.out.println("查询一个用户");
    }
}

添加的代理,通过原生的接口

public class AfterLog implements AfterReturningAdvice {
    //    o:返回值
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("执行了" + method.getName() + "方法,返回结果是" + o);
    }
}
public class Log implements MethodBeforeAdvice {
    //    method :要执行的目标对象的方法
    //    object:参数
    //    o:目标对象
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println(o.getClass().getName() + "的" + method.getName() + "被执行了");

    }
}

xml

<!--方式一:使用原生的API接口-->
<!--需要导入aop的约束-->
<aop:config>
    <!--切入点:pointcut-->
    <!--表达式:execution(要执行的位置)-->
    <aop:pointcut id="pointcut" expression="execution(* service.UserServiceImpl.*(..))"/>
    <!--执行环绕增强-->
    <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
    <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>

测试类

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        UserService service = context.getBean("userService", UserService.class);
        service.add();
    }
}

方式二:自定义类实现AOP

自定义代理类

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

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

xml

<!--方式二:自定义切入点类-->
<bean id="diy" class="diy.DiyPointCut"/>
<aop:config>
    <!--自定义切面引用的类-->
    <aop:aspect ref="diy">
        <!--切入点-->
        <aop:pointcut id="ponitcut" expression="execution(* service.UserServiceImpl.*(..))"/>
        <!--通知-->
        <aop:before method="before" pointcut-ref="ponitcut"/>
        <aop:after method="after" pointcut-ref="ponitcut"/>
    </aop:aspect>
</aop:config>

相比较来说,方式二更加的方便灵活

方式三:使用注解实现

xml

<!--方式三:使用注解-->
<bean id="diyAnnotationPointCut" class="diy.DiyAnnotationPointCut"/>
<!--开启注解支持-->
<aop:aspectj-autoproxy/>

service代理

@Aspect // 标注这个类是一个切面public class DiyAnnotationPointCut {    @Before("execution(* service.UserServiceImpl.*(..))")    public void before() {        System.out.println("注解配置的方法执行前");    }    @After("execution(* service.UserServiceImpl.*(..))")    public void after() {        System.out.println("注解配置的方法执行后");    }    @Around("execution(* service.UserServiceImpl.*(..))")    public void around(ProceedingJoinPoint joinPoint) throws Throwable {        System.out.println("环绕方法执行前");//        System.out.println(joinPoint.getSignature());        joinPoint.proceed();        System.out.println("环绕方法执行后");    }}

十一、回顾MyBatis

pom.xml(添加了spring依赖)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring</artifactId>
        <groupId>com.itlf</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>spring-10-mybatis</artifactId>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
        <!--spring操作数据库-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.13</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>

</project>

pojo

@Data
public class Student {
    private int id;
    private String name;
}

mapper接口

public interface StudentMapper {
    List<Student> selectStu();

}

mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="mapper.StudentMapper"><!--绑定接口-->
    <select id="selectStu" resultType="Student">
    select id,name from student
</select>
</mapper>

jdbc.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&rewriteBatchedStatements=true
username=root
password=123456

mybatis-config.xml

<?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>
    <!--配置jdbc的连接信息-->
    <properties resource="jdbc.properties"/>
    <!--别名-->
    <typeAliases>
        <package name="pojo"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <!--找到mapper文件,执行sql语句,一个mapper指定一个-->
    <mappers>
        <package name="mapper"/>
    </mappers>

</configuration>

test测试类

InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);

SqlSession session = sessionFactory.openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
List<Student> students = mapper.selectStu();
for (Student student : students) {
    System.out.println(student);
}

十二、Spring-MyBatis

http://mybatis.org/spring/zh/index.html 说明文档

MyBatis-SpringMyBatisSpring FrameworkSpring BatchJava
2.03.5+5.0+4.0+Java 8+
1.33.4+3.2.2+2.1+Java 6+

方式一

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring</artifactId>
        <groupId>com.itlf</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>spring-10-mybatis</artifactId>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
        <!--spring操作数据库-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.13</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>

</project>

mybatis-config.xml

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

    <!--别名-->
    <typeAliases>
        <package name="pojo"/>
    </typeAliases>


</configuration>

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

    <!--DateSource数据源   使用spring的数据源替换mybatis的-->
    <!--
    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&rewriteBatchedStatements=true
    username=root
    password=123456
    -->
    <bean id="dateSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url"
                  value="jdbc:mysql://localhost:3306/test?serverTimezone=UTC&amp;rewriteBatchedStatements=true"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>

    <!--SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dateSource"/>
        <!--绑定Mybatis配置文件-->
        <property name="configLocation" value="mybatis-config.xml"/>
        <!--mapper.xml-->
        <property name="mapperLocations" value="mapper/*.xml"/>
    </bean>

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

</beans>

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

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

    <!---->
    <bean id="stuMapper" class="mapper.StudentMapperImpl">
        <property name="sqlSession" ref="sqlSession"/>
    </bean>

</beans>

Student

package pojo;

import lombok.Data;

@Data
public class Student {
    private int id;
    private String name;
}

StudentMapper

package mapper;

import pojo.Student;

import java.util.List;

public interface StudentMapper {
    List<Student> selectStu();

}

StudentMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="mapper.StudentMapper"><!--绑定接口-->
    <select id="selectStu" resultType="Student">
      select id,name from student
    </select>
</mapper>

StudentMapperImpl

package mapper;

import com.mysql.jdbc.ConnectionPropertiesTransform;
import org.mybatis.spring.SqlSessionTemplate;
import pojo.Student;

import java.util.List;

public class StudentMapperImpl implements StudentMapper {
    private SqlSessionTemplate sqlSession;

    public StudentMapperImpl setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
        return this;
    }

    //    现在使用SqlSessionTemplate
    public List<Student> selectStu() {
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        return studentMapper.selectStu();
    }
}

MyTest

import mapper.StudentMapper;
import mapper.StudentMapperImpl;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pojo.Student;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

public class MyTest {
    @Test
    public void test() {

        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        StudentMapper stuMapper = context.getBean("stuMapper", StudentMapper.class);
        for (Student student : stuMapper.selectStu()) {
            System.out.println(student);
        }

    }
}

在这里插入图片描述

方式二

StudentMapperImpl2.java

public class StudentMapperImpl2 extends SqlSessionDaoSupport implements StudentMapper {

    public List<Student> selectStu() {
        return getSqlSession().getMapper(StudentMapper.class).selectStu();
    }
}

applicationContext.xml

<bean id="stuMapper2" class="mapper.StudentMapperImpl2">
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

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

    <!--DateSource数据源   使用spring的数据源替换mybatis的-->
    <!--
    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&rewriteBatchedStatements=true
    username=root
    password=123456
    -->
    <bean id="dateSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url"
                  value="jdbc:mysql://localhost:3306/test?serverTimezone=UTC&amp;rewriteBatchedStatements=true"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>

    <!--SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dateSource"/>
        <!--绑定Mybatis配置文件-->
        <property name="configLocation" value="mybatis-config.xml"/>
        <!--mapper.xml-->
        <property name="mapperLocations" value="mapper/*.xml"/>
    </bean>
</beans>

十三、声明式事务

回顾事务

要么都成功,要么都失败

事务在项目开发中,十分的重要,涉及 到数据的一致性的 问题

确保事务的完整性和一致性

事务的ACID原则:

原子性

一致性

隔离性

持久性

spring中的事务管理

声明式事务:AOP

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

为什么要使用事务?

如果我们不配置事务,可能存在数据提交不一致的情况

如果我们不在spring中去配置声明式事务,我们就需要在代码中手动配置事务

事务在项目的开发中十分重要,涉及到数据的完整性和一致性问题,不容马虎

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"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/tx
        https://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--DateSource数据源   使用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/test?serverTimezone=UTC&amp;rewriteBatchedStatements=true"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>

    <!--SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!--绑定Mybatis配置文件-->
        <property name="configLocation" value="mybatis-config.xml"/>
        <!--mapper.xml-->
        <property name="mapperLocations" value="mapper/*.xml"/>
    </bean>

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

    <!--配置声明式事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--结合aop实现事务的织入-->
    <!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--propagation="REQUIRED"  传播,默认的是REQUIRED-->
            <tx:method name="add" propagation="REQUIRED"/>
            <tx:method name="update"  propagation="REQUIRED"/>
            <tx:method name="delete" 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(* services.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>

</beans>

配置切面的传播

<tx:method name="add" propagation="REQUIRED"/>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值