文章目录
Spring
建议读者熟悉之前的maven、mybatis文章
一、Spring简介
- Spring于2003年兴起,是一个轻量级(核心jar包比较小,但是数量多)
- 非侵入式(框架代码不会侵入业务代码,业务代码不会实现或继承框架中接口或类)
- IOC(Inversionof Control反转控制/控制反转,由SpringIOC将所有使用对象进行管理)和AOP(面向切面编程,将公共功能进行提取,然后统一代码调用)的一站式框架,简化企业级应用开发
二、Spring体系结构
Core Container(核心容器)
- Beans: 管理 Beans
- Core: Spring 核心
- Context: 配置文件
- ExpressionLanguage: SpEL 表达式
AOP(切面编程)
AOP 框架: Aspects
Data Access(数据库整合) - JDBC, ORM, OXM, JMS, Transaction
Web(MVC Web 开发) - Web, Servlet, Portlet, Struts
- Test(Junit 整合)
官网地址:https://spring.io/
三、Spring基础框架的搭建
1.Maven导入spring核心基础jar
<!-- spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
2.编写spring配置文件 (.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="user" class="com.ff.spring.bean.User"> </bean>
</beans>
四、IOC(控制反转)
优点:在哪儿需要在哪儿注入即可,耦合性降低
- 读作“反转控制”(Inverse of Control)更好理解,不是什么技术,而是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由 Spring 框架来 管理。
- IOC 容器是具有依赖注入功能的容器,负责对象的实例化、对象的初始化,对象和对象之间依赖关系配置、对象的销毁、对外提供对象的查找等操作,对象 的整个生命周期都是由容器来控制。
- 我们需要使用的对象都由 ioc容器进行管 理,不需要我们再去手动通过 new 的方式去创建对象,由 ioc 容器直接帮我们组装好,当我们需要使用的时候直接从 ioc容器中直接获取就可以了。
- 正控:若要使用某个对象,需要自己去负责对象的创建
- 反控:若要使用某个对象,只需要从 Spring容器中获取需要使用的对象, 不关心对象的创建过程,也就是把创建对象的控制权反转给了 Spring 框架
- 底层实现方式: 解析 xml/扫描注解标签 + 工厂模式 + 反射机制
五、SpringBean的管理
1.基于XML的配置方式
- bean 配置需要 spring 管理的类
- id 生成的对象名
- class 全类名
- name 对象别名,可以为多个
scope:
- singleton(默认值):在 Spring 中只存在一个 bean 实例, 单例模式. prototype:原型
getBean()的时候都会 new Bean() - request:每次 http 请求都会创建一个 bean, 仅用于 WebApplicationContext 环境
- session:同一个 http session 共享一个 Bean, 不同 Session 使用不同的 Bean, 使用环境同上
2.XML配置方式的依赖注入
- 指 Spring 创建对象的过程中,将对象依赖属性(简单值,集合,对象)通 过配置设置给该对象。
- 实现 IOC 需要 DI 做支持
注入的方式:
- set 方法注入
- 构造方法注入
3.注解方式实现
注解开发准备工作
- 需要的 jar 包
- 注解功能封装在 AOP 包中,导入 Spring aop jar 包即可
开启注解扫描
<context:component-scan base-package="包名"> </context:component-scan>
注解创建对象
@Component(value=“user”)等于
<bean id=“user” class=“”></bean>
@Service
@Repository
以上注解都可以实现创建对象功能,只是为了后续扩展功能,在不同的层使用不同的注解标记
@Scope(value=“prototype”) 原型
@Scope(value=“ singleton ”) 单例
4.注解方式注入属性
@Autowired
- @Autowired 是 Spring 提供的注解,可以写在字段和 setter 方法上。如果写在 字段上,那么就不需要再写 setter方法。默认情况下它要求依赖对象必须存在, 如果允许 null 值,可以设置它的 required 属性为 false。
byType 自动注入
- 该注解默认使用按类型自动装配 Bean 的方式。
byName 自动注入
-
如果我们想使用按照名称(byName)来装配,可以结合@Qualifier 注解一起 使用。
-
需要在引用属性上联合使用注解@Autowired 与@Qualifier。
-
@Qualifier 的 value 属性用于指定要匹配的Bean 的 id 值。
JDK 注解@Resource 自动注入
-
Spring 提供了对 jdk 中@Resource 注解的支持。
-
@Resource 注解既可以按名 称匹配 Bean,也可以按类型匹配 Bean。
-
默认按照 ByName 自动注入 byName 注入引用类型属性
-
@Resource 注解指定其 name 属性,则 name 的值即为按照名称进行匹配 的 Bean 的 id
5.注解与XML的对比
- 注解优点: 方便,直观,高效(代码少,没有配置文件的书写那么复杂)。
- 注解缺点:以硬编码的方式写入到 Java 代码中,修改是需要重新编译代码的。
- xml 优点是: 配置和代码是分离的,在 xml 中做修改,无需编译代码,只需重 启服务器即可将新的配置加载。
- xml 的缺点是:编写麻烦,效率低,大型项目过于复杂。
六、SpringJDBC
- Spring 是个一站式框架:Spring 自身也提供了控制层的 SpringMVC 和 持久层的 Spring JdbcTemplate。
开发步骤 - 下载 Spring JdbcTemplate 与阿里数据源的 jar 包
<!-- spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<!-- 阿里数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
- 导入属性文件
<context:property-placeholder location="config.properties"/>
管理数据源对象
- spring 管理与数据库链接 (数据源)
<bean id="dataSource"class="com.alibaba.druid.pool.DruidDataSource">
<propertyname="driverClassName" value="${driverClassName}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${uname}"></property>
<property name="password" value="${pwd}"></property>
<property name="initialSize" value="10"></property>
<property name="minIdle" value="5"></property>
<property name="maxActive" value="20"></property>
</bean>
- 在配置文件中创建 JdbcTemplate
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
- 在类中获得 JdbcTemplate 对象,就可以直接使用。
JdbcTemplate 中常用的方法
-
execute:无返回值,可执行 ddl,增删改语句
-
update:执行新增、修改、删除语句;
-
queryForXXX:执行查询相关语句
七、AOP
1.AOP概述
-
AOP 为 Aspect Oriented Programming 的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。 AOP 是 OOP 的延续,是软件开发中的一个热点,是 java 开发中的一个重要内 容。利用 AOP 可以对业务逻辑和非业务逻辑进行隔离,从而使得各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
-
AOP、OOP 在字面上虽然非常类似,但却是面向不同领域的两种设计思想。OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获 得更加清晰高效的逻辑单元划分。
-
而 AOP 则是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。这两种设 计思想在目标上有着本质的差异。
-
面向切面编程的好处就是: 减少重复,专注业务;
-
注意:面向切面编程只是面向对象编程的一种补充。
核心原理:
- 使用动态代理的方式在执行方法前后或者出现异常的时候做加入相关的逻辑.
- 使用案例: 事务处理:开启事务,关闭事务,出现异常后回滚事务
- 权限判断:在执行方法前,判断是否具有权限 日志:在执行前进行日志处理
2.AOP的基本概念
- 连接点(Joinpoint):类中可以被增强的方法,这个方法就被称为连接点
- 切入点(pointcut):类中有很多方法可以被增强,但实际中只有 add 和 update被增了,那么 add 和 update 方法就被称为切入点(实际实现的连接点)
- 通知(Advice): 通知是指一个切面在特定的连接点要做的事情(增强的功能)。
- 通知分为方法执行前通知,方法执行后通知,环绕通知等.
- 切面(Aspect):把通知添加到切入点的整个过程称为切面. 目标(Target): 代理的目标对象(连接点,切入点所在类)
- 代理(Proxy): 向目标对象应用通知时创建的代理对象
3.SpringAOP实现
- 对于 AOP 这种编程思想,很多框架都进行了实现。Spring 就是其中之一,可 以完成面向切面编程。
- AspectJ 是一个基于 Java 语言的 AOP 框架,它提供了强大的 AOP 功能,且其实 现方式更为简捷,使用更为方便,而且还支持注解式开发。所以,Spring 又 将 AspectJ 的对于 AOP 的实现也引入到了自己的框架中。
下载 AOP 相关 jar
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
基于 aspectj 的 xml 配置方式实现
<!--让spring管理增强功能的类-->
<bean id="commonUtil" class="spring.util.CommonUtil"></bean>
<!--aop配置-->
<aop:config>
<!--配置切入点 切入点表达式-->
<aop:pointcut id="saveAdmin" expression="execution(* spring.dao.AdminDao.saveAdmin(..))"/>
<aop:aspect ref="commonUtil">
<aop:before method="saveLog" pointcut-ref="saveAdmin"></aop:before><!--前置处理-->
<aop:after method="saveLog" pointcut-ref="saveAdmin"></aop:after><!--后置处理-->
<aop:after-throwing method="exception" pointcut-ref="saveAdmin" throwing="e">
</aop:after-throwing><!--异常处理-->
<aop:around method="around" pointcut-ref="saveAdmin"></aop:around>
</aop:aspect>
</aop:config>
AspectJ 中常用的通知有五种类型:
- 前置通知,后置通知,环绕通知,异常通知,最终通知.
基于注解方式的实现
- 启动 AspectJ 支持:
<aop:aspectj-autoproxy />
定义通知:
@Component
@Aspect
public class AOPDemo {
@Before("execution(* com.ff.spring.demo1.dao.UserDao.*(..))")
public void before(){
System.out.println("before");
}
@After("execution(* com.ff.spring.demo1.dao.UserDao.*(..))")
public void after(){
System.out.println("after");
}
@Around("execution(* com.ff.spring.demo1.dao.UserDao.*(..))")
public void around(ProceedingJoinPoint point) throws Throwable {
System.out.println("start");
point.proceed();
System.out.println("end");
}
@AfterThrowing(value = "execution(* com.ff.spring.demo1.dao.UserDao.*(..))",throwing = "e")
public void afterthrow(Throwable){
System.out.println("afterthrow");
}
@AfterReturning("execution(* com.ff.spring.demo1.dao.UserDao.*(..))")
public void afterreturn(){
System.out.println("afterreturn");
}
}
八、Spring事务管理
-
例:转账、下单支付
-
一次对数据库操作,其中可能有多条sql语句,数据库要保证多条sql要一起执行成功,要么都不执行,数据库要对整个过程进行控制,成为数据库事务管理。
-
事务的原子性特征
-
事务是属于数据库特征
-
spring事务管理:指spring框架提供了对事务进行提交回滚的功能,帮助我们进行事务管理
-
sqlsesson.commit();
-
编程式事务:在业务代码中进行事务管理控制
-
声明式事务:可以通过xml;注解方式。对业务方法进行事务管理控制
-
@Transactional 可以作用在类和方法上>> 添加在类上,此类中所有方法都在事务管理中进行;添加在某个方法上,只对方法有效
Transactional自动事务管理会在以下情况中失效(声明式事务失效场景)
- ① 修饰一个非public的方法回导致事务失效
- ②方法中出现异常被try catch捕获,认为方法没有出现异常事务正常提交
- ③ 默认情况下出现编译期异常,会导致事务失效,rollbackFor=Exception.class(任何异常都不会提交事务)
- ④ 事务传播行为设置错误
- ⑤ 数据库引擎不支持事务,mysql中只有InnoDB引擎支持事务
- ⑥ 必须是Spring框架创建的类
- ⑦ 在同一个类的一个非事务方法中(一个调用一个,被调用的头上有),通过this调用事务方法,此时是通过非代理对象调用的,导致事务失效。
<!-- 配置 spring 事务管理类, 并注入数据源 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
注解方式
<!-- 开启注解事务管理 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
在 service 中控制事务
- @Service(value=“userservice”)
- @Transactional
九、Spring事务传播行为
传播:方法相互调用
-
Spring框架是独有的事务增强特性,是Spring框架自己提供的对事务的增强功能,与数据库事务无关,当A方法(有事务)调用了B方法,B方法应该如何执行,例如B方法是添加到A方法事务中进行,B方法继续是一个独立的方法。
-
PROPAGATION_REQUIRED:指定的方法必须在事务内执行,若当前存在事务,加入到当前事务中,若当前没 有事务,则创建一个新事务,这种传播行为是最常见的,也是spring 默认的传播行为
-
PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。 事务传播行为类型 说明
-
PROPAGATION_REQUIRED :如果当前没有事务,就新建一个事务,如果已经存在一个事务中, 加入到这个事务中。这是最常见的选择。
-
PROPAGATION_SUPPORTS : 支持当前事务,如果当前没有事务,就以非事务方式执行。
-
PROPAGATION_MANDATORY :使用当前的事务,如果当前没有事务,就抛出异常。
-
PROPAGATION_REQUIRES_NEW :新建事务,如果当前存在事务,把当前事务挂起。
-
PROPAGATION_NOT_SUPPORTED : 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
-
PROPAGATION_NEVER :以非事务方式执行,如果当前存在事务,则抛出异常。
-
PROPAGATION_NESTED : 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED 类似的操作。
-
PROPAGATION_REQUIRES_NEW:总是新建一个事务,如果当前存在事务,把当前事务挂起,直到新建的事务结束
十、Spring集成Mybatis
- Spring 集成 Mybatis 其核心是将 SqlSessionFactory 交由 Spring 管理,并由 Spring 管理对 dao 接口的代理实现。
导入 mybatis jar 包
Spring 结合 mybatis 插件包
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
配置 sqlSessionFactory
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="mybatis-config.xml"></property>
<property name="mapperLocations" value="com/ff/*Mapper.xml"></property>
</bean>
指定生成接口代理
<bean id="mapperFactory" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.ff.ssm.dao"></property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
在 service 中注入 Dao 代理接口,此接口有 Spring 代理实现