文章目录
spring
出现于2003年,用于减少企业开发的难度,帮助开发人员管理类和对象,管理不同的项目模块。
核心技术是控制反转(IoC)和面向切面编程(AOP)。
能够实现类之间的解耦合,可以管理类于类的依赖关系。
控制反转(IoC)是一种思想,将原本在由程序创建对象的权力交给spring框架,由框架创建对象,并且进行依赖注入(赋初值),不需要手动创建对象,想要使用对象时可以通过ioc容器获取。
spring bean管理
bean指的是由spring框架生成并管理的对象
xml配置
id=“生成对象的名称”
class="全类名"name=“自定义生成对象的名称” 可定义多个
springbean的作用域scope:
scope=singleton(默认值):单例的, 在Spring 中只存在一个 bean 实例, 单例的对象在Spring容器启动时就创建了,在Spring容器关闭时销毁。
scope=prototype:原型的 每次getBean()的时候都会创建新对象,每个对象的生命周期与其他java对象一样
<!--spring管理对象-->
<!--id="生成对象的名称" class="全类名"-->
<bean id="dogDao" class="com.yhl1.daoImpl.DogDaoImpl"></bean>
<bean id="dogService" class="com.yhl1.service.DogService">
<!--
name中的值表示对象中的属性名 ,且需要给该属性生成set方法
ref中的值表示 由spring容器创建出的对象名,将该对象注入给了dogService对象中的dogdao属性
ref表示引用
-->
<property name="dogdao" value="dogdao" ></property>
</bean>
实现IOC(spring创建对象) 时将对象的属性值进行赋值,这就叫做依赖注入
依赖注入优点--面向接口编程 具有低耦合高扩展性
注解配置
开启注解扫描
<context:component-scan base-package=“包名”> <</context:component-scan>>
注解创建对象
@Component(value=“user”) bean层
@Service 服务层
@Repository 数据持久层
以上注解都可以实现创建对象功能,只是为了后续扩展功能,在不同的层使用不同的注解标记
@Scope(value=“prototype”)原型
@Scope(value=“ singleton ”)单例
注解方式注入属性【DI:Dependency Injection】
byType 自动注入@Autowired
需要在引用属性上使用注解@Autowired,该注解默认使用按类型自动装配Bean 的方式。 使用该注解完成属性注入时,类中无需 setter。
byName 自动注入@Autowired 与@Qualifier需要在引用属性上联合使用注解@Autowired 与@Qualifier。
@Qualifier 的value 属性用于指定要匹配的 Bean 的 id 值。
JDK 注解@Resource 自动注入
Spring 提供了对 jdk 中@Resource 注解的支持。@Resource 注解既可以按名
称匹配 Bean,也可以按类型匹配 Bean。默认是按名称注入。
byName 注入引用类型属性
@Resource 注解指定其 name 属性,则 name 的值即为按照名称进行匹配
的 Bean 的 id。
注解与 XML 的对比
注解优点: 方便,直观,高效(代码少,没有配置文件的书写那么复杂)。
注解缺点:以硬编码的方式写入到 Java 代码中,修改是需要重新编译代码的。
xml 优点是: 配置和代码是分离的,在 xml 中做修改,无需编译代码,只需重
启服务器即可将新的配置加载。
xml 的缺点是:编写麻烦,效率低,大型项目过于复杂。
Spring JDBC
Spring 是个一站式框架:Spring 自身也提供了控制层的 SpringMVC 和 持久
层的 Spring JdbcTemplate。
开发步骤
1.先导入需要的jar包坐标,mysql,springjdbc,和阿里的德鲁伊数据库连接池
<!-- mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<!-- 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>
2.创建一个数据库连接配置文件,将文件导入总配置文件
<!--数据库连接管理-->
<import resource="db.xml"></import>
3.创建一个属性文件用于存储连接信息,注意用户名不要使用username命名
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/TED_db?characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
uname=root
password=123
initialSize=5
4.在db.xml中导入属性文件,将DruidDataSource对象交由spring框架创建,并将创建出的对象注入到jdbcTemplate对象中。
<!-- 导入属性文件-->
<context:property-placeholder location="JDBC.properties"/>
<!--spring 管理与数据库链接 (数据源)-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="${url}"> </property>
<property name="password" value="${password}"> </property>
<property name="username" value="${uname}"> </property>
<property name="driverClassName" value="${driver}"> </property>
<property name="initialSize" value="${initialSize}"> </property>
</bean>
<!--
在配置文件中创建 JdbcTemplate 用于向数据库发送spl
注入上面创建的dataSource对象
-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
5.以上操作完成后就可以在类中直接使用@Autowired注解标签获取JdbcTemplate对象,直接进行数据库相关操作,比如:
//增删改操作
jdbcTemplate.update("insert into user(name,sex) values ('王旭','男')");
jdbcTemplate.update("insert into user(name,sex) values (?,?)","恒力","男");
//ddl语句 操作表结构
jdbcTemplate.execute("");
//查询多个
List<Map<String, Object>> list = jdbcTemplate.queryForList("select * from user");
//查询单个
Map<String, Object> map = jdbcTemplate.queryForMap("select * from user where id = 4");
AOP 概述
什么AOP
AOP 为 Aspect Oriented Programming 的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。
AOP 是 OOP 的延续,利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。AOP、OOP 在字面上虽然非常类似,但却是面向不同领域的两种设计思想。OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。
而 AOP 则是针对业务处理过程中的公共功能进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。这两种设计思想在目标上有着本质的差异。面向切面编程的好处就是: 减少重复,专注业务;注意:面向切面编程只是面向对象编程的一种补充。
核心原理:使用动态代理的方式在执行方法前后或者出现异常的时候做加入相关的逻辑.
使用案例:
事务处理:开启事务,关闭事务,出现异常后回滚事务
权限判断:在执行方法前,判断是否具有权限
日志:在执行前进行日志处理
AOP的相关概念
连接点(Joinpoint):类中可以被增强的方法,这个方法就被称为连接点
切入点(pointcut): 类中有很多方法可以被增强,实际被增强的方法就是切入点
通知(Advice): 通知是指一个切面在特定的连接点要增强的功能。 切入点的增强功能就是通知 切面(Aspect): 把通知添加到切入点的过程叫切面.
目标(Target): 代理的目标对象(要增强的类)
代理(Proxy): 向目标对象应用通知之后创建的代理对象
其中通知可分为:
- 方法执行前通知,
- 方法执行后通知,
- 环绕通知等.
- 异常通知,
- 最终通知
xml 配置
开发步骤
1.先导入需要的jar包坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
2.装有通知的类
package com.yhl.aop;
import org.aspectj.lang.ProceedingJoinPoint;
public class Aop1 {
private void commit() {
System.out.println("提交事务");
}
private void dolog() {
System.out.println("保存日志");
}
public void around(ProceedingJoinPoint point) throws Throwable {
System.out.println("开启事务");
point.proceed();
System.out.println("提交事务");
}
public void throwable(Throwable e){
System.out.println("出异常了"+e.getMessage());
}
}
3.新建aop相关配置文件并导入主配置文件
<!--将装有增强功能(通知)的类交由 spring 管理.-->
<bean id="aopdemo" class="com.yhl.aop.Aop1"></bean>
<!--配置切入点和通知-->
<aop:config>
<!--配置切入点 *表示返回值 全类名.方法名(参数)-->
<aop:pointcut id="save" expression="execution(* com.yhl.dao.Dogdao.save(..))"/>
<!--配置通知 ref引入通知类-->
<aop:aspect ref="aopdemo">
<!-- method:通知类中的方法 pointcut-ref:配置的切入点
<aop:before method="dolog" pointcut-ref="save"></aop:before> 前置通知
<aop:after method="commit" pointcut-ref="save"></aop:after> 后置通知
<aop:around method="around" pointcut-ref="save"></aop:around> 环绕通知-->
<aop:after-throwing method="throwable" pointcut-ref="save" throwing="e"></aop:after-throwing> <!--异常通知 e代表方法参数-->
<aop:after-returning method="dolog" pointcut-ref="save"></aop:after-returning> <!--返回通知-->
</aop:aspect>
</aop:config>
4.测试
@Test
public void test(){
//默认启动时就会通过配置文件创建对象,需要时直接getBean就可以获取
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
DogService service = context.getBean(DogService.class);
service.save();
}
AOP注解配置
<!--开启aop注解-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
使用注解的装有通知的类
package com.yhl.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component // 将这个对象交给spring管理
@Aspect //标注装有通知的类
public class Aop1 {
private void commit() {
System.out.println("提交事务");
}
// @Before("execution(* com.yhl.dao.Dogdao.save(..))")
// @After("execution(* com.yhl.dao.Dogdao.save(..))")
private void dolog() {
System.out.println("保存日志");
}
@Around("execution(* com.yhl.dao.Dogdao.save(..))")
public void around(ProceedingJoinPoint point) throws Throwable {
System.out.println("开启事务");
point.proceed();
System.out.println("提交事务");
}
// @AfterThrowing(value = "execution(* com.yhl.dao.Dogdao.save(..))",throwing = "e")
public void throwable(Throwable e){
System.out.println("出异常了"+e.getMessage());
}
}
注解配置虽然在语法上比较简单,但是使用xml配置时逻辑更加清楚明了,建议先使用xml进行配置,可以加深学习印象。
Spring 事物管理
事物概念
什么是事物
事物可以看做是由对数据库若干操作组成的一个单元。
为什么需要事物
们在开发企业应用时,对于业务人员的一个操作实际是对数据读写的多步操作的结合。由于数据操作在顺序执行的过程中,任何一步操作都有可能发生异常,异常会导致后续操作无法完成,此时由于业务逻辑并未正确的完成,之前成功操作数据的并不可靠,需要在这种情况下进行回退。
事务的作用
就是为了保证用户的每一个操作都是可靠的,事务中的每一步操作都必须成功执行,只要有发生异常就回退到事务开始未进行操作的状态,这些操作要么都完成,要么都取消,从而保证数据满足一致性的要求
事务特征(ACID)
- 原子性(Atomic)
- 一致性(Consistent)
- 隔离性(Insulation)
- 持久性(Duration)
Spring 中的事务管理分为两种形式,一种是编程式事务,一种是声明式事务.
编 程 式 事 务
编 程 式 事 务 很 少 使 用 , 这 种 方 式 需 要 注 入 一 个 事 务 管 理 对 象TransactionTemplate ,然后在我们代码中需要提交事务或回滚事务时自己写代码实现.
声明式事务
声明式事务管理建立在 AOP 基础上,本质是对方法前后进行拦截,所以声明式事务是方法级别的。
Spring 声明式事物管理方式
Spring 事物管理 APIPlatformTransactionManager 事物管理器接口
Spring 针对不同的 dao 框架,提供了不同的实现类,Jdbc,mybatis 事物管理实现类是 DataSourceTransactionManager.
基于 xml 配置
<!--配置事物管理类-->
<!-- 配置 spring 事务管理类, 并注入数据源 -->
<bean id="transactionManager"class="org.springframework.jdbc.datasource.
DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置事物传播行为 -->
<tx:advice id="txadvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--aop切入点与通知进行绑定-->
<aop:config>
<aop:pointcut expression="execution(* com.yhl.dao.Dogdao.*(..))" id="allmethod"/>
<aop:advisor advice-ref="txadvice" pointcut-ref="allmethod"/>
</aop:config>
关于事物传播行为 会在下面讲解
基于注解实现
<!-- 开启注解事务管理 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
一般推荐在 service 中控制事务
@Service(value = "dogService")
@Transactional //使用在类上时,这个类中所有的方法都在事物中运行
Spring 事务传播行为
什么叫事务传播行为?
即然是传播,那么至少有两个东西,才可以发生传播。单体不存在传播这个行为。
事务传播行为(propagation behavior)指的就是当一个事务方法被另一个事
务方法调用时,这个事务方法应该如何进行。事务传播行为是 Spring 框架独有
的事务增强特性,他不属于的事务实际提供方数据库行为.
例如:methodA 事务方法调用 methodB 事务方法时,methodB 是继续在调
用者 methodA 的事务中运行呢,还是为自己开启一个新事务运行,这就是由
methodB 的事务传播行为决定的。
Spring 集成 Mybatis
导入 mybatis jar 包
<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>