前言:

  • 注意题目,这篇文章说的是操作,也就是重在应用,更多的是一个入门的或者说一篇概览,所以大佬们多多担待,不涉及底层分析和很多的源码,所以如果看官想看以上两者的可以划走了,有时间又不懒的话,可能以后会写个源码实现+分析的哈哈
  • spring存在的意义:一言以蔽之:解耦,为简化开发而生。程序员只需专注于业务代码实现,不必关心底层实现,并将程序员从大量机械重复的工作类似创建对象、数据库取出数据、导jar包等解脱出来,同时提高了程序的可靠性,大量避免因程序员管理对象不当等造成的问题。
  • spring优点:

    轻量;支持场景广泛;面向接口;面向切面;整合其他优秀框架

Spring概览

本文将从IOC;AOP;(这两者都是一种编程思想);spring整合MyBatis框架;事务这四个最重要的层面展开

而用框架,不管是spring还是其他的,说白了就是上环境,上依赖

spring 依赖

点击查看代码
    <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>

IOC

含义

控制反转,即将对象的创建权限和对象之间的依赖关系交给spring框架的容器

其实我的理解就像是做饭:

每次做饭都要买菜,择菜切菜,准备好佐料然后才是上锅炒,有时候没电气了还要先缴费,吃完了还得收拾桌子。

想想要是每次做都只管炒菜,其他的不管,爽不爽?spring就是干这个的,保证电气水充足,佐料都有,,买菜择菜洗菜就好比是根据产品经理的需求创建业务对象(注意不是写实体类),而这个也就是IOC,

接着话茬,吃完饭或者正在吃的要加量,就是后期运维,收拾碗筷就是产品下架了。

好了,有了我的抛砖,相信初学者会很容易理解。

正传反转

正转:由程序员进行对象的创建和依赖注入称为正转.程序员说了算.

反转:交由spring框架,也就是IOC

两种创建方式

一、xml方式

创建实体类对象

<bean id="stu" class="com.huijixu.bean.Students"></bean>

give values

  • manner1

    实体类必须提供setter()方法

    这里插嘴:如果该类在数据库里有主键,最好有主键的构造器和没有主键的构造器各搞一个。
<property name="" value=""></property>
  • manner2

    实体类必须提供该类相应成员变量的构造方法
<constructor-arg name="" value=""></constructor-arg>

还有按照下标的,意义不大也不常用,大家有兴趣可以自行查找很简单

  • manner3

引用类型的自动注入

  • byName

    按照成员变量的名字让spring去找,一般规范按照驼峰命名法
<property name="myname" value=""></property>
  • byType

    按照类型寻找在spring里和配置文件中同源的实体类注入,可与byName配合使用,比如上文byName 如果是在<bean id="Students" class="..."></bean>内的,那就是找是Students类的前提下,xml中对象名名称为myname的对象自动引用注入

二、注解方式

这种方式在中小项目中常用,本人认为注解比xml整洁美观

  • 在spring的配置文件applicationContext.xml中一定要添加包扫描,不添加包扫描spring就不知道去哪里找你写的注解,

  • 注解创建对象

    @Component :实体类

    @Service (k可以添加事务管理):ServiceImple实现类

    @Controller:控制类

    @Repository:数据访问层实现类对象创建

  • 注解给对象赋值

    @Value:八种基本类型+String

    @Autowired:一般用于service层实现类中对于dao层实现类的对象引用类型注入

    @Qualifier("名称") 当应用类型有别名时,它和@Autowried成套使用

配置文件拆分

  • 原因:

当项目体量逐步增大时,合理拆分易于缩小问题代码范围,通知在开发过程中易于成员间避免出现类似“幻读”的情况

  • 拆分策略:

按功能模块:

book;users;lead;

按层:mapper 、service、 controller

本人习惯于后者,因为这样可以和三层架构保持统一

  • 组合策略(以按层拆为例):

    一种直接在spring配置文件在中单写一个,再所拆分的配置文件import进来

    分批导入:

<import resource="applicationContest_service.xml"></import>
<import resource="applicationContest_mapper.xml"></import>
....

一次性:

<import resource="applicationContest_*.xml"></import>

要注意的几点

路径问题

  • spring.xml 创建业务对象

    <bean id="someService"class="com.huijixu.s01.SomeServiceImpl"></bean>

    这里的class一定是Copy Reference,部分初学者要么手写出错,要不路径用的是/分隔导致错误
  • SqlMapperConfig.xml标签一定注意顺序,错了不识别,具体顺序看jar里的说明来就行

命名规范

强烈建议新手cv!!

  • xml文件id名&接口方法名必须一致
  • 字段名&实体类成员变量名一致(可以不一致)
  • 成员变量名和sql语句中#{}内的名字一定要必须要一致
  • 接口名&对应实现类名必须一致(三层架构七大规范之一)

起别名(重复代码提取)

class,pom.xml,sql语句中,经常会出现大量重复的代码片段,而又不能在抽取细分,而这些又是轻易不会改变的,这时候就可以起别名(或者叫做全局变量)

开发的顺序

建立SQL表 -->搭建环境(pom文件,各种基础配置文件)-->

构建实体类-->mapper-->service-->controller-->

测试-->前后端绑定-->测试

这是本人的习惯顺序,有条理可以让开发有条不紊,即使出错了也有检查的大致判断,更是程序员基本素养

良好的单元测试习惯

写完一个功能,测一个功能,没毛病了再下一个,不然各个功能模块的bug一起报,不好调试

AOP

  • 在完成一项业务功能时,对那些重复用到的代码,抽取出来单独开发,然后随用随取,就是AOP,有些类似小项目中自定义的工具类
  • 还是用做饭的例子,炒菜的过程中的翻炒;或者说切菜时候的一下一下的切,这些重复的动作,而又是每个炒一道菜(完成一个业务功能)所必须的,就可以理解为AOP,实际开发中,日志,权限,缓存,提交事务等等这些公共通用的就是AOP
  • 其实原生的AOP实现是比较麻烦的,所以spring就把aspectJ整合进来了,用AspectJ实现AOP这种编程思想

spring原生AOP带来的优点

一言以蔽之:上接口使开发更美好

springAOP几种常见的通知类型

  • @Before
  • @After

    上面两者见名知义:分别在目标方法之前和之后调用
  • Around

    拦截目标方法,可以访问并且修改目标方法的返回值
  • Throws

    目标方法抛异常时使用,常用于事务回滚

AOP优秀框架:AspectJ

  • 产生原因:比原生AOP更容易使用
  • 两个核心概念:通知和切入点。前者解决何时切入;后者解决在哪切入
  • 几个术语:

    1.切面aspect:公共部分,用时动态织入

    2.连接点joinpoint;目标方法 ,链接业务功能与Buffer功能

    3.切入点pointcut:由一个及以上个连接点构成,包,类,方法都可以是切入点,但是final方法不可以作为切入点!!

    4.目标对象target:被加Buffer的对象,就是写主业务逻辑的有关对象,比如图书管理系统中,UsersServiceImpl就是一个target

所需依赖

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>

AspectJ切入点表达式:execution(访问权限 方法返回值 方法的声明(参数) 异常类型)

  • *标识任意
  • ..标识所有

    -e.g.: execution( * com.huijixu.service.impl..*(..)) 表示以任意访问权限任意返回值类型在com.huijixu.service.impl包下的任意class的任意方法名的任意参数的目标方法为切入点

AspectJ通知:advice

前置通知@Before
  • 方法规范

    • 方法访问权限是public
    • 方法的返回值是void
    • 名称自定义
    • 方法没有参数,如果有也只能是JoinPoint类型
    • 必须使用@Before注解来声明切入的时机是前切功能和切入点
    • 参数:value 指定切入点表达式
后置通知@AfterReturning
  • 方法规范

    • 访问权限是public
    • 2)方法没有返回值void
    • 3)方法名称自定义
    • 4)方法有参数(也可以没有参数,如果目标方法没有返回值,则可以写无参的方法,但一般会写有参,这样可以处理无参可以处理有参),这个切面方法的参数就是目标方法的返回值
    • 5)使用@AfterReturning注解表明是后置通知
环绕通知@Around
  • 方法规范

    • 访问权限是public
    • 切面方法有返回值,此返回值就是目标方法的返回值
    • 方法名称自定义
    • 方法有参数,此参数就是目标方法
    • 回避异常Throwable
    • 使用@Around注解声明是环绕通知
    • 参数: value:指定切入点表达式
最终通知@After
  • 方法规范

    • 访问权限是public
    • 方法没有返回值
    • 方法名称自定义

      * 方法没有参数,如果有也只能是JoinPoint

      * 使用@After注解表明是最终通知

      * 参数: value:指定切入点表达式

SSM整合的步骤

1)建表

2)新建项目,选择quickstart模板

3)修改目录

4)修改pom.xml文件,添加相关的依赖,spring依赖已经在前文贴出,下面是mybatis,mysql ,jdbc依赖

点击查看代码
<!--jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--myBaits -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!--mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<!--alibaba druid 连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
<!--mybatis集成spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>

5)添加MyBatis相应的模板,下面贴出自用的SqlMapperConfig.xml & XXXMapper.xml模板供大家使用

点击查看代码

```

<!--读取属性文件中数据库的配置-->
<properties resource="db.properties"></properties>
<!--设置日志输出语句,显示相应操作的sql语名-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<typeAliases>
<package name="com.bjpowernode.pojo"></package>
</typeAliases>
<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:3308/ssm?useSSL=false&amp;serverTimezone=UTC&amp;allowPublicKeyRetrieval=true"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="mapper文件所在的包名"></package>
</mappers>

```

点击查看代码

<!-- XXXMapper.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">
<mapper namespace="com.xxxxx.mapper.interface"> <!-- 就是接口的完全限定名,注意新手一定要右键 -> copy reference -> cv 防止不必要的错误--> </mapper>

6)添加MyBatis核心配置文件SqlMapConfig.xml,并拷贝jdbc.propertiest属性文件到resources目录下

同样给大家给书出。jdbc.properties,部分朋友可能会因为spring版本问题会报更新的错,虽然不影响使用但是影响美观哈哈,所以我的驱动加了'cj.'

点击查看代码

```
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf8
jdbc.username=yours mysql username
jdbc.password= yours password
```

7)添加applicationContext_mapper.xml

8)添加applicationContext_service.xml

9)添加实体类

10)添加mapper包,添加xxxMapper接口和xxxxMapper.xml文件并开发 (注意几个配套问题:文件名,方法名。。。)

11)添加service包,添加xxxService接口和xxxxServiceImpl实现类

12)添加测试类进行功能测试

事务

大白话就是,我不成,你也别想成,两个关联动作同时失败或者成功。保证数据的唯一性,一致性,原子性,隔离性;

依赖

点击查看代码
 <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>

记住一句话,项目中的所有事务,必须添加到业务逻辑层上.

事务隔离级别

  • mysql默认隔离级别为REPETABLE_READ:可重复读,这里简单提一嘴就是他可以解决脏读,不可重复读,但存在幻读
  • 未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据
  • 提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)
  • 可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读,但是innoDB解决了幻读
  • 串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞
  • 使用数据库默认的隔离级别isolation = Isolation.DEFAULT

Spring事务的传播特性

存在的意义

多个事务之间的合并,互斥等都可以通过设置事务的传播特性来解决

常用特性

  • PAGATION_REQUIRED:必被包含事务(增删改必用)
  • PAGATION_REQUIRES_NEW:自己新开事务,不管之前是否有事务
  • OPAGATION_SUPPORTS:支持事务,如果加入的方法有事务,则支持事务,如果没有,不单开事务
  • OPAGATION_NEVER:不能运行中事务中,如果包在事务中,抛异常
  • OPAGATION_NOT_SUPPORTED:不支持事务,运行在非事务的环境

下面贴一张网上找的图,总结的不错

其中B是嵌套在A中的事务

事务声明方式

xml文件声明步骤

  • 1)在applicationContext_service.xml文件中添加事务管理器

    ean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!--因为事务必须关联数据库处理,所以要配置数据源--> <property name="dataSource" ref="dataSource"></property> </bean>
  • 2)在applicationContext_service.xml文件中添加事务的注解驱动

    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
  • 3)在业务逻辑的实现类上添加注解@Transactional(propagation = Propagation.REQUIRED)

    REQUIRED表示增删改操作时必须添加的事务传播特性

下面以curd给出配置事物的代码

点击查看代码

```

<!--配置事务切面-->
<tx:advice id="myadvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*select*" read-only="true"/>
<tx:method name="*find*" read-only="true"/>
<tx:method name="*search*" read-only="true"/>
<tx:method name="*get*" read-only="true"/>
<tx:method name="*insert*" propagation="REQUIRED" no-rollback-for="ArithmeticException"/>
<tx:method name="*add*" propagation="REQUIRED"/>
<tx:method name="*save*" propagation="REQUIRED" no-rollback-for="ArithmeticException"/>
<tx:method name="*set*" propagation="REQUIRED"/>
<tx:method name="*update*" propagation="REQUIRED"/>
<tx:method name="*change*" propagation="REQUIRED"/>
<tx:method name="*modify*" propagation="REQUIRED"/>
<tx:method name="*delete*" propagation="REQUIRED"/>
<tx:method name="*remove*" propagation="REQUIRED"/>
<tx:method name="*drop*" propagation="REQUIRED"/>
<tx:method name="*clear*" propagation="REQUIRED"/>
<tx:method name="*" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
<!--绑定切面和切入点-->
<aop:config>
<aop:pointcut id="mycut" expression="execution(* com.bjpowernode.service.impl.*.*(..))"></aop:pointcut>
<aop:advisor advice-ref="myadvice" pointcut-ref="mycut"></aop:advisor>
</aop:config>

```

注解 @Transactional

@Transactional(propagation = Propagation.REQUIRED,//事务的传播特性

noRollbackForClassName = "ArithmeticException", //指定发生什么异常不回滚,使用的是异常的名称

noRollbackFor = ArithmeticException.class,//指定发生什么异常不回滚,使用的是异常的类型

rollbackForClassName = "",//指定发生什么异常必须回滚

rollbackFor = ArithmeticException.class,//指定发生什么异常必须回滚

timeout = -1, //连接超时设置,默认值是-1,表示永不超时

readOnly = false, //默认是false,如果是查询操作,必须设置为true.

isolation = Isolation.DEFAULT//使用数据库自已的隔离级别

有写错的地方希望大佬们海涵指出!!

快速了解Spring,简明Spring使用流程的更多相关文章

  1. SSH(Struts2+Spring+Hibernate)框架搭建流程<注解的方式创建Bean>

    此篇讲的是MyEclipse9工具提供的支持搭建自加包有代码也是相同:用户登录与注册的例子,表字段只有name,password. SSH,xml方式搭建文章链接地址:http://www.cnblo ...

  2. 只需两步!Eclipse+Maven快速构建第一个Spring Boot项目

     随着使用Spring进行开发的个人和企业越来越多,Spring从一个单一简介的框架变成了一个大而全的开源软件,最直观的变化就是Spring需要引入的配置也越来越多.配置繁琐,容易出错,让人无比头疼, ...

  3. 最简单易懂的Spring Security 身份认证流程讲解

    最简单易懂的Spring Security 身份认证流程讲解 导言 相信大伙对Spring Security这个框架又爱又恨,爱它的强大,恨它的繁琐,其实这是一个误区,Spring Security确 ...

  4. Spring Web MVC处理流程

    Spring Web MVC 处理流程: 1.浏览器向Spring发出请求,请求交给前端控制器 DispatcherServlet处理 2.控制器通过HandlerMapping找到相应的Contro ...

  5. Spring Bean的生命周期、Spring MVC的工作流程、IOC,AOP

    1.Spring Bean的生命周期? (1)构造方法实例化bean. (2)构造方法设置对象属性. (3)是否实现aware接口,三种接口(BeanNameAware,BeanFactoryAwar ...

  6. Spring Boot 自动装配流程

    Spring Boot 自动装配流程 本文以 mybatis-spring-boot-starter 为例简单分析 Spring Boot 的自动装配流程. Spring Boot 发现自动配置类 这 ...

  7. Spring 获取单例流程(三)

    读完这篇文章你将会收获到 Spring 何时将 bean 加入到第三级缓存和第一级缓存中 Spring 何时回调各种 Aware 接口.BeanPostProcessor .InitializingB ...

  8. Spring 获取单例流程(二)

    读完这篇文章你将会收获到 Spring 中 prototype 类型的 bean 如何做循环依赖检测 Spring 中 singleton 类型的 bean 如何做循环依赖检测 前言 继上一篇文章 S ...

  9. Spring详细基本开发流程

    LOGO 文章已托管到GitHub,大家可以去GitHub查看阅读,欢迎老板们前来Star! 搜索关注微信公众号 码出Offer 领取各种学习资料! 一.Spring概述 1.1 Web开发中的一些问 ...

  10. 企业快速开发平台Spring Cloud+Spring Boot+Mybatis+ElementUI 实现前后端分离

    鸿鹄云架构一系统管理平台 鸿鹄云架构[系统管理平台]使用J2EE技术来实施,是一个大型分布式的面向服务的JavaEE体系快速研发平台,基于模块化.服务化.原子化.热部署的设计思想,使用成熟领先的无商业 ...

随机推荐

  1. Mac安装swoole中遇到的问题

    转:https://blog.csdn.net/lishanleilixin/article/details/96137272 1:下载swoole源码,https://github.com/swoo ...

  2. 说说 Redis 哈希槽的概念?

    Redis 集群没有使用一致性 hash,而是引入了哈希槽的概念,Redis 集群有 16384 个哈希槽,每个 key 通过 CRC16 校验后对 16384 取模来决定放置哪个槽, 集群的每个节点 ...

  3. Less使用@import进行Mixins

    Import 指令 从其他样式表导入样式 在标准CSS中,@ import at-rules必须在所有其他类型的规则之前.但Less.js并不关心你放置@import语句的位置 Example: .f ...

  4. i2c总线编码

    i2c总线编码 发送启动信号S 在同步时钟线SCL 为高电平时,数据线出现的由高到低的下降沿. 启动信号子程序STA 1 /************************************** ...

  5. Kurento安装与入门02——运行示例前的准备

    官方一共提供了13个示例,这些示例运行的方式大同小异,一般会提供JAVA.Browser JavaScript.Node.js三种版本,这里仅演示java版本的示例.这些示例要求系统内已经正确安装了K ...

  6. 【wepy入门教程】48小时开发看美女微信小程序,万花阁

    说明:本文只做小程序的开发过程记录:小程序仅供学习参考,严禁用于商业及非法用途 准备 不管是做网站还是做小程序,只要是To C,就少不了做内容,因此第一步依然是数据准备,从网上找到两个网站: http ...

  7. java中Super指向他紧邻的父类,而不是最底层的基类

    3.2 当有两次继承时,演示super指向他紧邻的父类 我们把上面的例子扩展成两次继承, 就看出:马克-to-win,Super是一个参考(或说指针)指向他紧邻的父类,而不是最底层的基类. 例1.3. ...

  8. js多线程worker

    参考地址:https://blog.csdn.net/huang100qi/article/details/89303555?utm_source=app https://www.cnblogs.co ...

  9. 分库分表实现方式Client和Proxy,性能和维护性该怎么选?

    大家好,我是[架构摆渡人],一只十年的程序猿.这是分库分表系列的第一篇文章,这个系列会给大家分享很多在实际工作中有用的经验,如果有收获,还请分享给更多的朋友. 其实这个系列有录过视频给大家学习,但很多 ...

  10. python的编译和解释

    编译和解释 1.编译: 将源代码一次性转换成目标代码的过程 源代码 → 编辑器 →目标代码 →程序执行(同时程序输入)→结果输出 2.解释: 将源代码逐条转换成目标代码同时逐条运行的过程 源代码+程序 ...