四,Spring注解开发
创始人
2024-05-12 00:49:50
0

Spring day04

1 Spring基于注解的开发

XML方式配置bean存在的问题:开发效率低下。Spring2.x提供了开发效率更高的注解式配置。注解开发替换XML配置的好处:简化编程,提高开发效率。

  • XML方式:配置繁琐,但功能强大,维护性好,可配置第3方类型(非自己编码的类型)
  • 注解方式:配置简单,开发效率高。一般用于自定义类型的配置

1.1 注解开发的思路

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lQL1p8z8-1673747421009)(Spring day04.assets/image-20210617223657666.png)]

1.2 注解开发的步骤

  1. 查找注解,配置查找注解的起始包名

    applicationContext.xml

     
    
    
  2. 为类和属性添加注解

    package com.bz.service.impl;import com.bz.entity.User;
    import com.bz.mapper.UserMapper;
    import com.bz.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;@Component("userService")
    public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;public void setUserMapper(UserMapper userMapper) {this.userMapper = userMapper;}@Overridepublic boolean login(String name, String password) {User user = userMapper.selectUserByName(name);return user!= null && user.getPassword().equals(password);}}
    

1.3 核心注解

1.3.1 bean配置相关注解

@Component替换bean标签,创建对象。

@Controller 用在action层
@Service 用在service
@Repository 用在dao层

@Service
//@Component("userService")
public class UserServiceImpl implements UserService {@Autowiredprivate UserDao userDao;public void setUserDao(UserDao userDao) {this.userDao = userDao;}...
}

注意:

  1. Controller Service Repository和Component作用一样,但更有识别性。

  2. MyBatis框架下,Repository注解没有必需的使用场景

  3. 4个注解使用时,都可以不用设置id属性,id默认值:类名首字母小写

    例如:UserServiceImpl ==> userServiceImpl

@Scope 决定对象是否单例

​ 默认对象是单例的,可以通过@Scope(“prototype”)设置为多例

1.3.2 属性注入的相关注解

@Autowired 用来完成属性注入。

@Service
public class UserServiceImpl implements UserService {@Autowired(required = false)private UserDao userDao;public void setUserDao(UserDao userDao) {this.userDao = userDao;}...
}

注意:

  1. Autowired根据属性的类型,从Spring容器中获取对象,完成属性赋值
  2. Autowired用在属性上,通过反射直接操作属性为属性赋值,不会使用set方法
  3. Autowired还可以用在set方法上,此时通过调用属性的set方法赋值
  4. Autowired修饰的属性默认是必须的,如果注入失败就会抛出异常;可以设置@Autowired(required=false)允许注入失败

@Qualifier(“bean的id”)

与@Autowired配合使用,当有多个满足属性类型要求的Bean时,可以用@Qualifier(“id”)来指定要注入的依赖。

class Address{private String city;private String address;...
}




class Person{private String personName;@Autowired@Qualifier("addr1")private Address addr;...
}

@Value用于为简单属性赋值,还可以读取properties文件中的参数

jdbc.properties

url=jdbc:mysql://localhost:3306/spring?useUnicde=true&characterEncoding=utf-8&useSSL=false&serverTimeZone=Asia/Shanghai
driverClassName=com.mysql.cj.jdbc.Driver
user=root
password=123456

JdbcProeprties.java

@Component
public class JdbcProperties{//@Value("root")@Value("${user}")private String username;@Value("${password}")private String password;@Value("${url}")private String url;@Value("${driverClassName}")private String driverClassName;...
}

行业标准:

  1. 自定义类型Service、Dao使用注解开发
  2. 第3方类型:数据库连接池、事务管理器…使用xml配置

2 基于注解的事务控制

使用Transactional注解描述类或者方法添加事务。

开发步骤:

  1. 创建原始对象

  2. 定义通知类(功能增强:事务控制)

    Spring内置的DataSourceTransactionManager

  3. 配置通知类

    
    
    
    
  4. 使用Transactional注解描述类或方法

    @Service
    @Transactional
    public class UserServiceImpl implements UserService {@Autowiredprivate UserDao userDao;@Transactional(readOnly=true)@Overridepublic boolean login(String name, String password) {User user = userDao.selectUserByName(name);return user!= null && user.getPassword().equals(password);}public void register(String username,String password){userDao.insertUser(new User(null,username,password));}
    }
    

注意:

传统的Spring项目中,注解的事务控制使用较少,更多的还是使用xml配置的事务控制。但是在SpringBoot中大量的使用注解方式的事务配置。

3 Spring集成JUnit

直接使用JUnit测试Spring项目,需要手动编码获取context工厂,需要手动从工厂中获取对象,测试繁琐。
解决方案:使用Spring-test,简化了Spring项目的测试。

准备工作:导入JUnit、spring-test依赖


junitjunit4.12test

org.springframeworkspring-test5.2.8.RELEASE

测试:

//开启Spring对Junit的支持
@RunWith(SpringRunner.class)
//设置配置文件的路径
@ContextConfiguration("classpath:applicationContext.xml")
public class ApplicationContextTest {//自动从工厂中获取对象,为属性赋值@Autowiredprivate ApplicationContext context;@Autowiredprivate UserMapper userMapper;@Autowiredprivate UserService userService;...
}

小技巧:如果有多个测试类,多个测试类上方也有重复的配置,可以定义父类抽取共性

//开启Spring对Junit的支持
@RunWith(SpringRunner.class)
//设置配置文件的路径
@ContextConfiguration("classpath:applicationContext.xml")
public abstract class AbstractApplicationContextTest {
}public class ApplicationContextTest extends AbstractApplicationContextTest{@Autowiredprivate UserService userService;...
}

4 再谈web.xml

4.1 web.xml标签的加载顺序

目前为止学习的标签:servlet filter listener context-param

加载顺序:

  1. context-param
  2. listener
  3. filter
  4. servlet

4.2 servlet的url-pattern配置形式以及优先级

url-pattern配置形式种类:

  1. 精确匹配

    /student/showPageStudents

  2. 路径匹配

    /* /student/*

  3. 扩展名匹配

    *.jsp *.do *.action

  4. 缺省匹配

    / 在前3种都无法匹配时做默认匹配

优先级:精确匹配>路径匹配>扩展名匹配>缺省匹配

注意:

  1. 都是路径匹配时,最长路径优先

    http://localhost:8989/spring-day05/student/b

    /student/* 比/* 优先匹配到。

  2. 路径匹配和扩展名匹配不能混用

    不能出现如下配置:

    /student/*.do

    / * / *.jsp

另外注意:

  1. Filter一定早于Servlet执行
  2. 多个Filter执行的优先级只跟配置顺序有关,跟url-pattern的优先级没有关系

5 事务详解(概念重点)

5.1 read-only

read-only="true"表示只读事务,提高查询(检索)效率。read-only的默认值是false。
注意:只能应用到查询操作,不能应用到增删操操作上。



5.2 timeout

timeout超时机制(单位秒):事务执行时间超过指定的时长后,自动失败回滚。
timeout默认值-1:表示跟数据库的默认超时设置有关。

//通过sleep方法,模拟业务方法执行超时
public void removeUser(Integer id) {try {Thread.sleep(5000);//当前线程睡眠5s} catch (InterruptedException e) {e.printStackTrace();}userDao.deleteUserById(id);
}


@Test
//测试超时
public void testTimeout(){ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");UserService userService = (UserService)ctx.getBean("userServiceImpl");userService.removeUser(1);
}

5.3 rollback-for和no-rollback-for

rollback-for:当发生rollback-for配置的异常类型的异常时,执行回滚。
no-rollback-for:当发生no-rollback-for配置的异常类型的异常时,不执行回滚。

Spring中默认:

RuntimeException及其子类(运行时异常)的异常执行回滚

Exception及其子类(编译时异常)的异常不会执行回滚

public void addUser(User u) {userDao.insertUser(u);// throw new RuntimeException("自定义未检查异常");//默认回滚throw new Exception("自定义已检查异常");//默认不回滚
}

rollback-for和no-roollback-for的生效规则:

  • 2个的属性本身没有优先级区别
  • 程序产生的异常,与哪个属性中配置的异常类型继承关系更近就是用哪个配置
  • 如果产生的异常和配置的异常类型没有继承关系,则使用默认规则

5.4 propagation(传播机制)

企业开发中,会出现业务层方法调用业务层方法的情况。propagation定义了一个业务方法被另外一个业务方法调用时的事务传播方式。

常用的事务传播机制:

传播机制内部方法对事务的要求特点
REQUIRED必须有如果外部有事务,则加入;外部没有事务,则新建
REQUIRES_NEW必须有无论外部是否有事务,内部都会新建
SUPPORTS可有可无如果外部有事务则加入;如果没有则以无事务状态运行
NOT_SUPPORTED必须没有如果外部有事务,则挂起外部事务
MANDATORY必须有如果外部没有事务,直接抛出异常
NEVER必须没有如果外部有事务,直接抛出异常
NESTED必须有如果外部没有事务,开启事务;如果外部有事务,记录当前的保存点;一旦出错,不会全部回滚,只回滚到保存点

5.5 isolation(隔离级别)

解决事务并发执行的问题,微观上,2个执行时间相近的事务相互影响的问题。

5.5.1 4种标准的隔离级别

隔离性在数据库的并发访问时得以体现,随着数据库并发事务处理能力的大大增强,数据库资源的利用率也会大大提高,从而提高了数据库系统的事务吞吐量,可以支持更多的用户并发访问。但并发事务处理也会带来一些问题,如:脏读、不可重复读、幻读。这些问题是和隔离性相伴相生的。下面一一解释其含义。

  • 脏读

    B事务正在对一条记录做修改,在这个事务提交前,这条记录的数据就处于不一致状态;这时,另一个事务A也来读取同一条记录,如果不加控制,第二个事务读取了这些未提交的(“脏”)数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被形象的叫作"脏读"(Dirty Reads)。

  • 不可重复读

    一个事务中多次执行相同的查询SQL,不同时刻读取的数据不同。要么发现其读出的数据已经发生了改变、或某些记录已经被删除了!这种现象就叫作“ 不可重复读”(Non-Repeatable Reads)。

  • 幻读

    一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为“幻读”(Phantom Reads)。

隔离级别特点存在的问题
READ-UNCOMMITTED读未提交脏读、不可重复读、幻读
READ-COMMITTED读已提交只能读到另外一个事务提交后的数据。不可重复读、幻读
REPEATABLE-READ可重复读同一个事务下,前后两次结果一致不同数据库不同,有的数据库会有幻读
SERIALIZABLE序列化读串行性能太差

Oracle只支持READ-COMMITTED和SERIALIZABLE 2种隔离级别。

MySQL支持4种。

实战时,使用读已提交即可。

5.5.2 MySQL下演示隔离级别

MySQL支持多种存储引擎:InnoDB(支持事务)、MyISAM、MEMORY

存储引擎:决定了数据库如何的保存管理数据。

  1. 确认MySQL使用的存储引擎
show engines;//查询数据库支持的存储引擎
show variables like 'default_storage_engine';//查询默认引擎

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3NbDFE9k-1673747421010)(Spring day04.assets/image-20200406163015651.png)]

  1. 查询当前使用的隔离级别:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mk7KSqyh-1673747421011)(Spring day04.assets/image-20200406163149179.png)]

  2. 修改当前使用的隔离级别:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QZGwkePr-1673747421011)(Spring day04.assets/image-20200406163503131.png)]

  3. MySQL中开启事务和结束事务

    >start transaction;//开启事务
    >commit;//提交
    >rollback;//回滚
    

隔离级别

准备工作:

create table t_account(id int primary key,money double
);
start transaction;
insert into t_account values(1,100);
insert into t_account values(2,200);
commit;
  1. 读未提交隔离级别[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sRqsFGUG-1673747421012)(Spring day04.assets/image-20200406170439133.png)]

    脏读:B事务未提交,A事务可以读取到B事务插入的数据

  2. 读提交隔离级别

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9SrrMkJY-1673747421012)(Spring day04.assets/image-20210508221628304-1624412671148.png)]

    B事务不提交,A事务读取不到。B事务提交后A事务就可以读取到。

    仍存在的问题:不可重复读和幻读

  3. 可重复读隔离级别

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pxcOqJoQ-1673747421013)(Spring day04.assets/image-20210509185633571.png)]

  4. 序列化读

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RjhwJf7f-1673747421013)(Spring day04.assets/image-20200406171658872-1624412785930.png)]

    文章对应源码地址:https://download.csdn.net/download/qq_36827283/87386038

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...