Spring
1.spring基础部分
spring是什么?
Spring 是一个轻量级的,IOC 和 AOP 的一站式 Java 开发框架,是为了简化企 业级应用开发而生的。
轻量级
Spring 框架使用的 jar 都比较小,一般在 1M 以下或者几百 kb。Spring 核 心功能的所需的 jar 总共在 3M 左右。 Spring 框架运行占用的资源少,运行 效率高。
IOC
即 Inversion of Control,缩写为 IOC,是由 Spring 管理对象,而非传统实现 中由程序代码直接操控. 以前需要什么对象,需要在程序中new对象.现在,spring思想是,将对象的生成1和管理统一交给框架,我们需要的时候,直接从框架获取即可
Inversion of Control 读作“反转控制”(Inverse of Control)更好理解,不是什么技术,而是一种 设计思想,就是将原本在程序中手动创建对象的控制权,交由 Spring 框架来 管理。
IOC 容器负责对象的实例化、对象的初始化,对象和对象之间依赖关系、 对象的销毁、对外提供对象的查找等操作,对象的整个生命周期都是由容器来 控制。
Bean
由spring框架创建的对象,与自己new的原生对象不一致
spring如何管理Bean?
方法一:基于xml(了解)
<bean id="admin" class="com.ffyc.springpro.model.Admin" name="admin2" scope="singleton"></bean>
<!--bean指的是spring框架创建的对象,spring框架创建的对象和我们自己new的对象有区别
bean 配置需要 spring 管理的类
id 生成的对象名
class 全类名
name 对象别名,可以为多个
scope:
singleton(默认值):在 Spring 中只存在一个 bean 实例, 单例模式. 在启动spring框架时就会创建对象
prototype:原型 getBean()的时候都会 new Bean()
request: 每次http请求都会创建一个bean,仅用于WebApplicationContext环境
-->
</beans>
ApplicationContext applicationContext= new ClassPathXmlApplicationContext("spring.xml");//启动spring容器
Admin admin=applicationContext.getBean("admin",Admin.class);//从spring框架中获取需要的对象
依赖注入
spring创建对象的同时,为对象中的属性进行赋值,有的属性值可能来源于另外一个对象
方法一:通过属性的set方法注入
<bean id="admin" class="com.ffyc.springpro.model.Admin" name="admin2" scope="singleton">
<property name="account" value="admin"></property>
<property name="id" value="1"></property>
<property name="password" value="123"></property>
</bean>
方法二:通过有惨的构造方法赋值
<constructor-arg name="id" value="1"></constructor-arg>
方法二:基于注解(常用)
<?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
http://www.springframework.org/schema/context/spring-context.xsd
">
<!--开启注解扫描 对指定包下面的类进行扫描,检测添加有spring注解标签的类-->
<context:component-scan base-package="com.ffyc.springpro"> </context:component-scan>
</beans>
注解创建对象 @Component(value=“user”)等同于
@Service @Repository 以上注解都可以实现创建对象功能,只是为了后续扩展功能,在不同的层使用不 同的注解标记 @Scope(value=“prototype”) 原型 @Scope(value=“ singleton ”) 单例
注解方式注入属性【DI:Dependency Injection】
@Autowired @Autowired 是 Spring 提供的注解,可以写在字段和 setter 方法上。如果写在 字段上,那么就不需要再写 setter 方法。默认情况下它要求依赖对象必须存在, 如果允许 null 值,可以设置它的 required 属性为 false。 byType 自动注入 该注解默认使用按类型自动装配 Bean 的方式。 byName 自动注入 如果我们想使用按照名称(byName)来装配,可以结合@Qualifier 注解一起 使用。 需要在引用属性上联合使用注解@Autowired 与@Qualifier。@Qualifier 的 value 属性用于指定要匹配的 Bean 的 id 值。
方式1:使用spring框架中的@Autowired 可以添加到注入的属性上面,或者属性的set方法上,如果直接添加在属性上,那么set方法可以不需要
默认情况下,要注入的属性对象不能为空@Autowired(required=true)
注入时查找bean的方式有两种:1.通过对象名查找 需要使用@Qualifier(value=“admindao”)2.通过属性的类型查找
方式2:使用jdk中提供的注解
JDK 注解@Resource 自动注入 Spring 提供了对 jdk 中@Resource 注解的支持。@Resource 注解既可以按名 称匹配 Bean,也可以按类型匹配 Bean。默认按照 ByName 自动注入 byName 注入引用类型属性 @Resource 注解指定其 name 属性,则 name 的值即为按照名称进行匹配 的 Bean 的 id。
AOP
Aspect Oriented Programming 直译过来就是面向切面编程。AOP 是一种编 程思想,是面向对象编程(OOP)的一种补充。面向对象编程将程序抽象成各 个层次的对象,而面向切面编程是将程序抽象成各个切面.也是一种编程思想,可以为我们的程序动态添加某种功能,而不用修改原来的代码
AOP 为 Aspect Oriented Programming 的缩写,意为:面向切面编程,通过 预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。 AOP 是 OOP 的延续,是软件开发中的一个热点,是 java 开发中的一个重要内 容。利用 AOP 可以对业务逻辑和非业务逻辑进行隔离,从而使得各部分之间的 耦合度降低,提高程序的可重用性,同时提高了开发的效率。 AOP、OOP 在字面上虽然非常类似,但却是面向不同领域的两种设计思想。OOP (面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获 得更加清晰高效的逻辑单元划分。 而 AOP 则是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的 某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。这两种设 计思想在目标上有着本质的差异。
面向切面编程的好处就是: 减少重复,专注业务;
注意:面向切面编程只是面向对象编程的一种补充。
核心原理: 使用动态代理的方式在执行方法前后或者出现异常的时候做加入相关的逻辑.
使用案例: 事务处理:开启事务,关闭事务,出现异常后回滚事务
权限判断:在执行方法前,判断是否具有权限
日志:在执行前进行日志处理
AOP 面向切面编程,是一种将非业务代码与业务代码进行分离的一种思想,把业务代码进行抽取,然后再运行时让框架帮我们调用即可,做到了业务代码和非业务代码分离,实现低耦合度,将非业务代码进行抽取,在不修改原来代码的前提下,为业务代码添加额外的功能. 底层使用动态代理技术让一个代理对象帮助我们调用非业务代码.
AOP思想不是spring中特有的,是java中的动态代理模式.是spring框架中使用了这一思想.
spring中如何使用AOP
连接点(Joinpoint):类中可以被增强的方法,这个方法就被称为连接点
切入点(pointcut):类中有很多方法可以被增强,但实际中只有 add 和 update 被增强了,那么 add 和 update 方法就被称为切入点(实际实现的连接点)
通知(Advice): 通知是指一个切面在特定的连接点要做的事情(增强的功能)。通 知分为方法执行前通知,方法执行后通知,环绕通知等.
目标(Target): 代理的目标对象(连接点,切入点所在类)
代理(Proxy): 向目标对象应用通知时创建的代理对象(目前使用的代理对象由spring框架生成)
对于 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 中常用的通知有五种类型: 前置通知,后置通知,环绕通知,异常通知,返回通知.
/*
@Before 前置通知 在方法执行前调用
@After 后置通知 在方法执行后调用 即使出现异常也会执行
@AfterReturning 在方法成功执行完之后调用 出现异常则不会执行
@AfterThrowing 异常通知,当切入点出现异常时调用
@Around 环绕通知
*/
/*
* 环绕通知 可以在方法执行前 后 异常 添加功能,一个通知就可以实现
* proceedingJoinPoint 表示我们要增强的方法
*/
@Around("execution(* com.ffyc.spring.dao.*.*(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint){
try {
System.out.println("前置通知");
proceedingJoinPoint.proceed();//调用自己的方法
Object[] objects = joinPoint.getArgs();//获取调用方法的参数
System.out.println("返回通知");
} catch (Throwable throwable) {
System.out.println(throwable.getMessage());
//throwable.printStackTrace();
//异常通知
}
System.out.println("后置通知");
}
一站式框架
Spring 本身也提供了数据访问功能和 web 功能,以及可以很好的管理其他框架.在IOC和AOP的基础上,spring框架还对数据访问层和web层都进行了封装
注解与 XML 的对比 注解优点
方便,直观,高效(代码少,没有配置文件的书写那么复杂)。 注解缺点:以硬编码的方式写入到 Java 代码中,修改是需要重新编译代码的。 xml 优点是: 配置和代码是分离的,在 xml 中做修改,无需编译代码,只需重 启服务器即可将新的配置加载。 xml 的缺点是:编写麻烦,效率低,大型项目过于复杂。
spring对数据访问层进行管理(IOC应用)
以前连接数据库的对象,都是我们自己创建的,现在使用spring之后,我么可以将连接数据库的对象,交给spring管理,在哪儿里使用,就在那里注入即可
spring集成mybatis
Spring 集成 Mybatis 其核心是将 SqlSessionFactory 交由 Spring 管理,并由 Spring 管理对 dao 接口的代理实现
导入 mybatis jar 包
Spring 结合 mybatis 插件
配置 sqlSessionFactory
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<property name="mapperLocations" value="classpath:mappers/*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代理实现
spring事务管理
事物可以看做是由对数据库若干操作组成的一个单元。
我们在开发企业应用时,对于业务人员的一个操作实际是对数据读写的多步 操作的结合。由于数据操作在顺序执行的过程中,任何一步操作都有可能发生异 常,异常会导致后续操作无法完成,此时由于业务逻辑并未正确的完成,之前成 功操作数据的并不可靠,需要在这种情况下进行回退。
事务的作用就是为了保证用户的每一个操作都是可靠的,事务中的每一步操 作都必须成功执行,只要有发生异常就回退到事务开始未进行操作的状态,这些 操作要么都完成,要么都取消,从而保证数据满足一致性的要求 Spring 中的事务管理分为两种形式,一种是编程式事务,一种是声明式事务. 编程式事务在项目中很少使用,这种方式需要在我们代码中需要提交事务或回滚 事务时自己写代码实现. 声明式事务管理建立在 AOP 基础上,本质是对方法前后进行拦截,所以声明式 事务是方法级别的。
Spring 声明式事物管理方式有两种: 基于 xml 配置 基于注解实现 Spring 的 dao 框架,提供事物管理实现类是 DataSourceTransactionMana
数据库事务是一次对数据库执行的若干操作的管理,这一次操作的若干条sql语句,应该是一个整体的单元.例如转账:一次转账操作,对于用户来讲是一个操作,但是这一次操作中,会执行多条sql语句.多条语句是一个整体,要么都执行,要么都不执行.只有完成一次操作后,向数据库提交事务后,数据库才会将多条sql真正执行.
事务保证了数据的完整性,不能一半保存到数据库,一半没保存成功.
spring事务管理在AOP的基础上,当我们的方法完全成功执行后,在提交事务,如果方法中有异常,就不提交事务.
spring中事务管理有两种方式:
1.编程式事务:需要我们在编程中手动提交
2.声明式事务:基于 xml 配置 基于注解实现
Spring 的 dao 框架,提供事物管理实现类是 DataSourceTransactionMan
配置事物管理器
<!-- 配置 spring 事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 开启注解事务管理 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
在类或方法上使用@Transactional 标签即可 可以添加在类上 类中的所有方法都在事务管理中进行,也可以添加在方法,所添加的方法在事务管理中进行
声明式事务失效场景:
/*
1.@Transactional用在了非public方法上面
2.异常被catch捕获了, 认为方法没有出现异常
3.默认出现编译期异常, 可以在@Transactional(rollbackFor = Exception.class)设置回滚异常类型为Exception,这样即使出现编译期异常,也是有效的
4.数据库引擎不支持事务 , mysql中只有innodb引擎支持事务
*/