Spring教程

@Test
public void getUsers1(){
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserMapper userMapper = context.getBean(UserMapper.class);
    List<User> users = userMapper.getUsers();
    System.out.println(users);
}

1、Spring简介

官网API: https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-p-namespace

Spring Framework 为现代基于 Java 的企业应用程序提供了一个全面的编程和配置模型 - 在任何类型的部署平台上。

Spring 的一个关键元素是应用程序级别的基础设施支持:Spring 专注于企业应用程序的“管道”,以便团队可以专注于应用程序级业务逻辑,而无需与特定部署环境产生不必要的联系。

Spring是Full-stack轻量级框架, Java EE的春天,当前主流框架。数据访问层Dao MVC部分,Web部分。

Spring的核心理念就是面向bean的编程。

2、控制反转

将组件对象的控制权由代码本身转移到外部容器。

发现传统方式,如果切换了实现类就必须在代码中更改实现类,这种方式就是耦合度很高,违反了spring的思想,组件化配置。

3、Spring程序开发步骤

3.1.添加依赖spring-webmvc

导入基本包坐标:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.6</version>
</dependency>
3.2.编写Dao接口和实现类
3.3创建Spring核心配置文件
<?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>
3.4.在Spring配置文件中配置UserDaoImpl
<bean id="usreMapper" class="cn.hxzy.dao.impl.UserMapperImpl"></bean>
3.5.使用Spring的API获得Bean实例
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
public boolean save() {
    UserMapper userMapper = (UserMapper) context.getBean("userMapper");
    Integer count = userMapper.save();
    if (count > 0) {
        return true;
    }
    return false;
}

4、依赖注入

把对象的属性值,通过容器来注入到对象实体中去

4.1、构造方法注入
4.1.1 按照构造函数的参数索引值位置进行注入
<bean id="user" class="cn.hxzy.pojo.User">
    <constructor-arg index="0" value="zhangsan"/>
    <constructor-arg index="1" value="20"/>
</bean>
4.1.2 按照构造函数的参数类型进行注入

注意,如果按类型进行匹配注入,配置的是基本数据类型,则在class中定义的属性也必须为基本数据类型。如果为包装类,定义的时候也必须为包装类型。

<bean id="user" class="cn.hxzy.pojo.User">
    <constructor-arg type="java.lang.String" value="lisi"/>
    <constructor-arg type="java.lang.Integer" value="24"/>
</bean>

bean标签的作用范围

singleton默认的,单例的
prototype多例的
requestSpringWeb应用中,创建一个bean对象后,存入到request作用域
sessionSpringWeb应用中,创建一个bean对象后,存入到sessiont作用域

 

4.1.3 引用注入
<bean id="user" class="cn.hxzy.pojo.User">
    <constructor-arg index="0" value="zhangsan"/>
    <constructor-arg index="1" value="20"/>
    <constructor-arg ref="dog"/>
</bean>
<bean id="dog" class="cn.hxzy.pojo.Dog">
    <constructor-arg index="0" value="旺财"/>
    <constructor-arg index="1" value="3"/>
</bean>
4.2、设值注入
4.2.1 properties属性注入

setter器

public void setUserName(String userName) {
     this.userName = userName;
}

xml配置

<!-- 设值注入-->
<bean id="stu" class="cn.hxzy.pojo.Student">
    <property name="userName" value="qyy"/>
</bean>
4.2.2 p-namespace p命名空间注入

配置,头文件中引入

xmlns:p="http://www.springframework.org/schema/p"
4.3 注入其他复杂数据类型

复杂数据类型的bean配置

<bean id="data" class="cn.hxzy.news.test.DataCategroy">
    <property name="strs">
        <array>
            <value>html</value>
            <value>vue</value>
            <value>spring</value>
        </array>
    </property>
    <property name="list">
        <list>
            <value>java</value>
            <value>jdbc</value>
            <value>maven</value>
        </list>
    </property>
    <property name="map">
        <map>
            <entry key="ch" value="中国"/>
            <entry key="en" value="英国" />
            <entry key="us" value="美国"/>
            <entry key="ru" value="俄罗斯"/>
        </map>
    </property>
</bean>

5、Bean标签的范围配置

Java中共有23种设计模式。单例模式是其中之一,在应用程序运行起来,类加载后,内存中产生了一个唯一的对象。

单例模式分为两种:1、懒汉模式 2、饿汉模式

6、Bean的自动装配方式

6.1 XML配置
<bean id="user" class="cn.hxzy.pojo.User" autowire="byName">
    <property name="userName" value="zhangsan"/>
    <property name="userAge" value="30"/>
    <property name="userId" value="100"/>
</bean>
<bean id="dog" class="cn.hxzy.pojo.Dog">
    <property name="dogColor" value="黄色"/>
    <property name="dogName" value="旺财"/>
</bean>

 

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

byType 会自动在容器上下文中查找,和自己对象属性类型相同的bean,如果在容器存在相同类型的对象,则不能使用byType。

6.2 java中显式的进行配置

使用java的注解,也必须spring配置文件中配置context约束

@Resource与@Autowired的区别:
@Resource是java的注解,默认是按照名称进行装配,相当于是@Autowired加@Qualifier(value = "user")的合体
@Autowired是spring的注解,默认是按照类型进行装配

相同点
   都是用来自动装配的,都可以放在属性字段上
不同点
    @Autowired通过byType的方式实现,必须要求这个对象存在
    @Resource默认通过byName的方式实现,如果找不到名字,则通过byType实现。
6.2 spring注解配置

参考7.5

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

步骤:

7.1 引入依赖
7.2 编写spring的核心配置文件
7.3 引入context约束配置信息
<?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>
7.4 配置注解的支持
<!--启用注解配置-->
<context:annotation-config/>
7.5 自动扫描标注注解的包
<!--在容器启动的时候,对标注注解的包进行自动扫描,扫描到以后自动进行注册到容器-->
<context:component-scan base-package="cn.hxzy"/>
7.6 常用注解的说明

@Component //相当于在spring配置文件中定义的bean节点,当容器加载的时候,扫描包以后就会进行注册到IOC容器

根据@Component注解衍生出一些注解:

@Repository 代表数据访问层

@Service 代表业务逻辑层, 通常情况会给他加名称 @Service(value = "userService")

@Controller 代表控制层

@Autowired 注解实现的bean的自动装配,默认是按照类型去装配的,如果容器中出现了两个类型相同的bean,则需要添加注解

@Qualifier(value = "jdbcMysqlDao")//根据名称来自动装配

@Resource是java自己的注解,默认按照名称来自动装配,如果该bean没有名称,则按照类型进行装配

@Configration 相当于spring核心配置文件里面的beans

@Bean:用于@Configration配置类中,声明一个对象让spring容器管理,一般用于整合其他框架后,把它的类注册为bean实例对象后供spring来调度使用的。

@PropertySource("classpath:application.properties")读取静态资源目录下指定名称的properties文件

@Value("${name}")

@Bean与 @Component的区别:
两者都是Spring框架中用于定义bean的注解,但它们的用途和范围有所不同。以下是两者的区别:

作用对象不同:@Bean注解作用于方法,用于显式声明单个bean,而@Component注解作用于类,用于自动检测和使用类路径扫描自动配置bean。

配置方式不同:@Bean注解通常与@Configuration注解一起使用,允许开发者精确地创建和配置bean,提供更多关于bean的配置信息,如初始化方法、作用域、命名等;@Component注解则更多用于自动装配到Spring容器中,适用于简单的业务类。

使用场景不同:@Bean适用于需要更精细控制的bean配置,如第三方库中的类;@Component适用于简单的业务类或组件。

总结来说,如果需要简单地将一个类声明为bean,可以使用@Component;如果需要详细配置bean或从方法中产生bean,则应使用@Bean。
package cn.hxzy.config;

import cn.hxzy.domain.Person;
import cn.hxzy.domain.User;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

/**
 * @author:mengshujun
 * @createTime: 2024-04-02 09:41:19 星期二
 */
@Configuration  //代表着这个类就可以做为spring的配置类
@PropertySource(value = "classpath:Person.properties", encoding = "utf-8")
public class SpringConfig {

    @Value("${personName}")
    private String personName;
    @Value("${personAge}")
    private int personAge;

    @Bean
    public Person person() {
        return new Person(personName,personAge);
    }

//    @Bean  
//    public User user(){
//        return new User("root","123");
//    }
}

Person.properties文件

personName=张三丰
personAge=156

8、Aop的简介

AOP是面向切面编程的意思,全称为Aspect Oriented Programing。

他是一种基于OOP之上的一种编程范式,弥补了OOP的不足,能更好的组织程序结构。

AOP可以把业务的功能步骤做成插拔式的组件,从而可以用这些组件定制新的功能,因此AOP可以提高业务的复用性,提高开发效率。

把现有的代码做增强处理

public class MathDemo{

    public int f1(int n1,int n2){

           return n1+n2;
    }

    public int f2(int n1,int n2){

           return n1-n2;
    }


    public int f3(int n1,int n2){

           return n1*n2;
    }

}
public class jdbcDemo{


    Connection conn;
    
    public void exectuUpdate(){
    
        //编程式事务:代码的侵入性很高
    
        //
        conn.commit(); //提交
        
        //异常
        conn.rollback(); //回滚
    
    }

}

9、 代理模式

9.1 角色分析

真实角色:被代理的角色 代理角色:代理真实角色。代理真实角色后,我们一般会做一些附属操作,比如收房租等等。

9.2 代理模式的好处

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

9.3 代码实现

定义接口

/*
* 出租房屋
* */
public interface RentHouse {
    //出租房屋
    void czfw();
}

定义真实对象

/*
* 房东类
* */
public class FangDong implements RentHouse{
    public void czfw() {
        System.out.println("出租房屋.....");
    }
}

定义代理对象

/*
* 中介公司
* */
public class Proxy {
    /*代理类的属性:房东对象*/
    private FangDong fangDong;
    public Proxy(){}

    public Proxy(FangDong fangDong){
        this.fangDong=fangDong;
    }

    /*出租房屋*/
    public void czfw(){
        fangDong.czfw();
    } 

}

10、Spring使用AOP

AOP的一些相关名词

  • 切面(Aspect):横切关注点被模块化的特殊对象,是一个类,里面可以定义切入点和通知(切面 = 切点+通知)

  • 通知(Advice):切面必须要完成的工作,是类中的一个方法

  • 切入点(pointCut):切面通知执行的位置

  • 连接点(JointPoint):程序执行过程中明确的点,一般是方法的调用

XML方式实现步骤:

10.1、引入依赖

spring aop与aspectj

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>
10.2、在核心配置文件中导入aspectj约束
<?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"
       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/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">  

</beans>
10.3、定义日志类
package cn.hxzy.log;

import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
@author:mengshujun
@createTime: 2024-04-02 14:39:27 星期二
*/
@Component("beforeLog")
public class LoggerProgram implements MethodBeforeAdvice {

    /**
     * 前置增强
     * @param method  执行的目标方法
     * @param objects  参数列表数组,如果目标方法无参,则为null
     * @param o 目标对象
     * @throws Throwable
     */
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("执行方法的当前时间为:"+ LocalDateTime.now());
        System.out.println("目标对象的方法名称为:"+method.getName());
        System.out.println("方法的参数为:");
        for (Object object : objects) {
            System.out.println(object);
        }
        System.out.println("目标对象的类型为:"+o.getClass().getName());
    }
}

后置通知:

package cn.hxzy.log;

import org.springframework.aop.AfterReturningAdvice;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
@author:mengshujun
@createTime: 2024-04-02 15:50:25 星期二
*/
@Component("afterLog")
public class LoggerAfter implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("执行方法完成的时间为:"+ LocalDateTime.now());
        System.out.println("目标对象的方法名称为:"+method.getName());
        System.out.println("方法的参数为:");
        for (Object object : objects) {
            System.out.println(object);
        }
        System.out.println("目标对象的类型为:"+o1.getClass().getName());
        System.out.println("方法的返回值为:"+o);
    }
}

环绕通知:

package cn.hxzy.log;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * @author:mengshujun
 * @createTime: 2024-04-02 15:57:58 星期二
 */
@Component("around")
public class AroundTest implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {

        System.out.println("方法开始执行,时间为:" + LocalDateTime.now());
        long start = System.currentTimeMillis(); //系统时间戳 1970.1.1
        
        Object rs=methodInvocation.proceed(); //目标方法进行调用执行
        
        System.out.println("方法执行完成,时间为:" + LocalDateTime.now());
        long end = System.currentTimeMillis();
        System.out.println("所用时间为:" + (end - start));
        System.out.println("方法的返回值为:"+rs);
        return rs; //方法的返回值
    }

}
10.4、搭建项目结构
@Repository
public class UserDaoImpl implements UserDao {
    public int register(String userNo,String userPwd) {
        System.out.println("您注册的信息为:"+userNo);
        System.out.println("您注册的密码为:"+userPwd);
        return 1;
    }
}
10.5、在核心配置文件中添加AOP的配置
<!--aop:xml的配置-->
<aop:config>
    <!--定义切入点-->
    <aop:pointcut id="point" expression="execution(* cn.hxzy.dao.impl.*.*(..))"/>
    <!--定义通知-->
    <!--<aop:advisor advice-ref="beforeLog" pointcut-ref="point"/>-->
    <aop:advisor advice-ref="afterLog" pointcut-ref="point"/>
</aop:config>

通知类型:

前置通知:方法执行前进行的代码编织,xml配置实现接口:MethdBeforeAdvice

后置通知:方法执行后进行的代码编织 xml配置实现接口:AfterReturningAdvice

环绕通知:方法执行前后都进行代码编织,区别于前置+后置。把目标方法进行了围绕,无论是否发生异常都会被执行。xml配置实现接口:MethodInterceptor

最终通知:

异常通知:

切入点表达式:
execution(* cn.hxzy.dao.impl.*.*(..))
第一个* 表示的是方法任意的返回值
第二个* 表示任意的类
最后一个*表示的是任意的方法

11、使用注解来定义切面

好处:1、增加了代码的灵活度 2、减少了配置代码量

使用@Aspect,首先要保证所用的JDK 是5.0或以上版本

@Aspect 标注这个类是一个切面

@Before("execution(* cn.hxzy.dao.Impl.UserDaoImpl.*(..))") 前置通知

@AfterReturning("execution(cn.hxzy.dao.Impl.UserDaoImpl.(..))") 后置通知

@AfterThrowing 异常通知, 在方法抛出异常之后

@Around 环绕通知, 围绕着方法执行

@After 最终增强

<!---开启aspectj框架的自动代理-->
<aop:aspectj-autoproxy expose-proxy="true" />

注解示例:

package cn.hxzy.log;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * @author:mengshujun
 * @createTime: 2024-04-02 16:47:08 星期二
 */
@Aspect
@Component
public class AdviceLog {

    @Pointcut("execution(* cn.hxzy.dao.impl.*.*(..))")
    public void pt(){}

    //前置通知
    @Before("AdviceLog.pt()")
    public void beforeLog(JoinPoint joinPoint) {
        //得到代理对象的签名信息
        Signature signature = joinPoint.getSignature();
        Class c1 = signature.getDeclaringType();
        System.out.println("方法名:" + signature.getName());
        System.out.println("类名:" + c1.getName());
        System.out.println("参数信息:");
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            System.out.println(arg);
        }
    }

    //后置通知
    @AfterReturning(returning = "result", pointcut = "AdviceLog.pt()")
    public void afterLog(JoinPoint joinPoint, Object result) {
        System.out.println("方法执行完毕后的时间为:" + LocalDateTime.now());
        System.out.println("方法的执行返回结果为:" + result);
    }

    //环绕通知
    @Around("AdviceLog.pt()")
    public Object around(ProceedingJoinPoint joinPoint) {
        System.out.println("方法开始执行,时间为:" + LocalDateTime.now());
        long start = System.currentTimeMillis(); //系统时间戳 1970.1.1
        //调用方法本身去执行
        Object result = 0;
        try {
            result = joinPoint.proceed();  //调用方法....
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("所用时间为:" + (end - start));
        System.out.println("方法的返回值为:" + result);
        return result;
    }

}

AOP应用场景:一般应用于针对核心业务的辅助功能,包括,事务处理,日志,系统安全,监控等场景中。使用横切代理的方式把辅助代码织入到核心方法之中。

通过AOP,可以降低业务逻辑各部分之间的耦合度,提高程序的可重用性,同时提高开发的效率和系统的可维护性。

12、Spring集成Mybatis

1、IOC spring创建对象,给对象的属性赋值,完成对对象的管理。

2、AOP 在不影响核心业务代码的基础上,把公共的一部分基础业务,抽取到切面中,然后在程序的编译器(运行期)通过代理的方式,实现代码的织入。

spring官方的孵化器

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId> 
    <version>2.0.6</version>
</dependency>

mybatis对整合spring框架所做的补丁包

什么是 MyBatis-Spring?

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

版本信息:

MyBatis-Spring 需要以下版本:

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

spring整合mybatis的步骤:

12.1 导入依赖
<dependencies>
    <!-- junit测试包 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
    
    <!-- mybatis-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.7</version>
    </dependency>

    <!-- mysql驱动包 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.29</version>
    </dependency>

    <!--lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.20</version>
        <scope>provided</scope>
    </dependency>

    <!-- Spring 相关-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.8</version>
    </dependency>
    
    
    <!-- spring 操作jdbc-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.3.8</version>
    </dependency>


    <!--AOP相关-->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.7.M3</version>
    </dependency>

    <!--mybatis整合spring的补丁包-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.6</version>
    </dependency>

    <!--阿里巴巴的数据源连接池-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.18</version>
    </dependency>
    
</dependencies>

Hibernate:C3P0

12.2 创建maven集成的mybatis项目

编写接口的映射xml文件,在业务逻辑层,数据访问层(@Mapper),添加注解

spring核心配置文件的头信息:

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

</beans>

mybatis的核心配置文件

<?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">
<!--mybatis的核心配置文件-->
<configuration>
    <settings>
        <!--全局开启二级缓存-->
        <setting name="cacheEnabled" value="true"/>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <setting name="autoMappingBehavior" value="FULL"/>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <typeAliases>
        <package name="cn.hxzy.pojo"/>
    </typeAliases>

    <!--注册  映射器-->
    <mappers>
        <mapper resource="mapper/UserMapper.xml"></mapper>
    </mappers>
</configuration>
12.3 编写了数据源druid.properties
druid.driver=com.mysql.jdbc.Driver
druid.url=jdbc:mysql://localhost:3306/ticket?serverTimezone=UTC&useUnicode=true&useSSL=false&characterEncoding=utf8
druid.username=root
druid.password=root

druid.pool.init=5
druid.pool.minIdle=5
druid.pool.maxActive=100
druid.pool.maxWait=30000
12.4 编写了spring的核心配置文件

读取数据源

<!--spring读取properties文件-->
<context:property-placeholder location="classpath:druid.properties"/>

<!--数据源连接池-->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${druid.driver}"/>
    <property name="url" value="${druid.url}"/>
    <property name="username" value="${druid.username}"/>
    <property name="password" value="${druid.password}"/>
    <property name="initialSize" value="${druid.pool.init}"/>
    <property name="minIdle" value="${druid.pool.minIdle}"/>
    <property name="maxActive" value="${druid.pool.maxActive}"/>
    <property name="maxWait" value="${druid.pool.maxWait}"/>
</bean>

注册sqlSessionFactoryBean

<!--Spring注册SqlSessionFactory对象-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="druidDataSource"/>
    <property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>

 可以为dao层的接口注册成spring容器所管理的接口对象(只可以注册单个的Mapper对象)

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

<!--newsMapper的bean实例对象-->
<bean id="newsMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    <property name="sqlSessionTemplate" ref="sqlSession"/>
    <property name="mapperInterface" value="cn.hxzy.mapper.NewsMapper"/>
</bean>

可以简写为:

指定扫描基准包,把包下面面的接口注册成spring容器所管理的接口对象

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="cn.hxzy.dao"/>
</bean>
<context:annotation-config />
<context:component-scan base-package="cn.hxzy"/>
<aop:aspectj-autoproxy expose-proxy="true"/>
12.5 测试
@Test
public void getUsers1(){
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserMapper userMapper = context.getBean(UserMapper.class);
    List<User> users = userMapper.getUsers();
    System.out.println(users);
}

 

13、静态资源的过滤配置

在dependencies下面,project节点里面添加如下配置:

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

14、声明式事务

14.1事务的XML配置方式

编程式的事务,代码侵入性较高。可移植性,可维护性差。

编程式事务:写在代码里面,硬编码进去的事务语句,就属于编程式事务。弊端:1.代码侵入性较高,耦合度高。2.繁琐,复用性低。

公共性的代码,aop

Connection conn;
//执行sql
conn.commit(); //提交
//
conn.roallback(); //回滚

事务的概念:把一组SQL指令打包一个独立的语句模块执行,如果里面有任意一条语句执行失败,则整个语句执行操作都将会回滚。

四个特性:1、原子性 2、持久性 3、隔离性 4、一致性

通俗

原子性:一组sql,一批sql是一个最小的执行单元,不可分割
持久性:执行命名令后,产生的结果是永久性的,不可逆转。
隔离性:两个及以上的并发事务执行的时候,互不影响
一致性:事务执行前后,对数据的操作产生的影响是一致的。

声明式事务:把要完成的事务操作,定义在一个其他类中,当核心业务模块执行的时候,把事务通过代码的方式织入到核心业务中来。AOP

事务管理器的配置:

<!-- 定义事务管理器-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="druidDataSource"/>
</bean>


<!--配置切点,引用通知-->
<aop:config>
    <aop:pointcut id="mypoint" expression="execution(* cn.hxzy.service.impl.*.*(..))"/>
    <aop:advisor  advice-ref="myAdvice" pointcut-ref="mypoint"/>
</aop:config>


<!--通知-->
<tx:advice transaction-manager="txManager" id="myAdive">
    <!--事务规则-->
    <tx:attributes>
        <tx:method name="zhuanZhang" propagation="REQUIRED"/>
        <tx:method name="delete*" propagation="REQUIRED"/>
        <tx:method name="insert*" propagation="REQUIRED"/>
        <tx:method name="update*" propagation="REQUIRED"/>
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>
14.2 事务的隔离级别

描述的是两个及以上的并发事务,执行的过程中,针对事务之间的互相影响的情况的一种应对策略。

并发事务可能出现的问题:

脏读:事务1执行的过程中,事务2读取到了事务1修改过但还未提交的数据,这种情况就叫做脏读。

不可重复度:事务1先后读取同一条记录,但两次读取的数据不同,原因是在这之间事务进行数据的修改,并提交了,导致事务1两次读取到的数据不同,称之为不可重复读

幻读:事务1按照条件查询数据时,没有对应的数据行,在这期间,事务2查询了对应的数据行,并且进行了提交,之后事务1在插入对应的数据时,又发现这行数据已经存在,好像出现了幻觉。

DEFAULT :采用的JDBC的隔离级别

4==SERIALIZABLE 串行化: T1在执行的过程中,T2既不能读与不能写

3=REPEATABLE_READ 可重复读(mysql):T1在执行的过程中,T2只读与不能修改数据,T2可以添加数据,可能会导致T1幻读 (幻读)

2=READ_COMMITTED 读已提交 (oracle):T1在执行的过程中,T2可以读也可以写,但是T1只能读取到T2提交后的数据(幻读)(不可重复读)

1=READ_UNCOMMITTED 读未提交:T1在执行的过程中,T2可以读也可以写,T1可以读取到T2未提交的数据(幻读)(不可重复读)(脏读)

14.3 事务的传播机制

REQUIRED: 如果上层方法没有事务,则创建一个新的事务,如果已经存在事务,则加入到事务中。

SUPPORTS: 如果上层方法没有事务,则以非事务方式执行。如果已经存在事务,则加入到事务中。

REQUIRES_NEW: 如果上层方法没有事务,则创建一个新的事务。如果已经存在事务,则将当前事务挂起,创建新事务执行。

NOT_SUPPORTED:如果上层方法没有事务,则以非事务方式执行。如果已经存在事务,则将当前事务挂起,以非事务方式执行。

NEVER: 如果上层方法没有事务,则以非事务方式执行。如果已经存在事务,则将当前事务挂起,并抛出异常。

MANDATORY: 如果上层方法没有事务,则抛出异常,如果已经存在事务,则加入到事务重执行。

NESTED:如果上层方法没有事务,则创建一个新的事务,如果已经存在事务,则嵌套到当前事务中。

14.4 事务的其他属性

timeout:事务超时时间,允许事务运行的最长时间,以秒为单位。默认值为-1,表示不超时

read-only:事务是否为只读,默认值为false

rollback-for:设定能够触发回滚的异常类型、Spring默认只在抛出runtime exception时才标识事务回滚、可以通过全限定类名指定需要回滚事务的异常,多个类名用逗号隔开

no-rollback-for:设定不触发回滚的异常类型、Spring默认checked Exception不会触发事务回滚、可以通过全限定类名指定不需回滚事务的异常,多个类名用英文逗号隔开

<tx:method name="transferAccount"
                       isolation="REPEATABLE_READ"
                       propagation="REQUIRES_NEW"
                       timeout="-1"
                       no-rollback-for="java.lang.ArithmeticException"
                />
14.5 使用注解的形式实现声明式事务的配置

可以直接配置在类上或者方法上

@Service
@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRES_NEW,noRollbackFor = ArithmeticException.class)
public class TransferAccountServiceImpl implements TransferAccountService {
    
}

 也可以叫灵活的配置在所需要的方法上

@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRES_NEW,noRollbackFor = ArithmeticException.class)
public boolean transferAccount(int fromUserId, int toUserId, double money) {
     
}

在配置文件中添加上,注解事务的支持

<!--启动注解方式的支持-->
<tx:annotation-driven transaction-manager="txManager"/>

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值