今天我们来学习一个新的框架spring!!!
spring是什么呢?
spring是2003年兴起的,是一款轻量级、非侵入式的IOC和AOP的一站式的java开发框架,为简化企业即开发而生。
轻量级:spring核心功能的jar包不大
非侵入式:我们的业务代码不需要继承或实现spring中的任何类和接口
IOC:控制反转,以前项目都是在哪儿用到对象,在哪儿new,把生成对象的权利反转给spring框架
Aop:面向切面编程
一站式框架:
- 提供核心功能,主要是IOC,创建管理对象
- 提供面向切面编程,增强程序扩展
- 对数据访问层进行了封装(重点在事务管理)
- 对Web层进行封装,使得请求更加的便捷
Spring思想是什么?由框架统一对项目的类进行管理(创建对象,后期增强一些功能),在需要的地方注入即可。
Core Container(核心容器):
- Beans: 管理 Beans
- Core: Spring 核心
- Context: 配置文件
IOC(控制反转):就是将原本在程序中手动创建对象的控制权,交由 Spring 框架来
管理。
在Spring Bean对象管理
- 基于xml配置管理
<bean id="adminservice" class="com.ffyc.ssm.service.AdminService">
<property name="adminDao" ref="adminDao"></property><!--注入-->
</bean>
让spring帮我们管理项目中的类 方式1:在xml中进行配置 配置需要让spring进行管理的类 id="唯一的标识" class="让spring管理的类名" bean? 由spring框架创建并管理的对象称为一个bean对象 Scope="singleton 默认值" 单例的 在整个应用程序中只创建一个对象,在spring框架启动时就创建好了 prototype 原型的 每次获取时创建一个对象,可以创建多个 spring框架创建对象时,需要为对象的属性进行赋值操作: 这个赋值操作称为依赖注入 1.属性赋值 getXXX,setXXX方法 2.构造方法赋值
- 注解方式实现
- 注解开发准备工作
- 注解需要的 jar 包
- 注解功能封装在 AOP 包中,导入 Spring aop jar 包即可
- 开启注解扫描
<context:component-scan base-package="包名"> </context:component-scan>
5. 注解创建对象
@Component(value=“user”)等于
<bean id=“user” class=“”></bean>
@Service
@Repository
以上注解都可以实现创建对象功能,只是为了后续扩展功能,在不同的层
使用不同的注解标记
@Scope(value=“prototype”)
原型
@Scope(value=“ singleton ”)
单例
注解方式注入属性
/* * Map("adminDao,AdminDao",对象) * @Autowired * spring框架中提供的一个自动注入注解标签 * 有两种方式去查找对象: * 1.byType 去spring容器中根据当前类型进行搜索 * 2.byName 通过名称查找 需要结合当前@Qualifier(value="adminDao") * @Autowired(required=true) 注入时,对象值不能为空,为空的话会进行报错 * *@Resource * 是jdk中提供的一个注解标签 * 有两种方式去查找对象: * 1.byType 去spring容器中根据当前类型进行搜索 * 2.byName 通过名称查找 @Resource(name="adminDao") * */ // @Autowired // @Qualifier(value="adminDao")
注解与XML的对比
- 注解优点: 方便,直观,高效(代码少,没有配置文件的书写那么复杂)。
- 注解缺点:以硬编码的方式写入到 Java 代码中,修改是需要重新编译代码的。
- xml 优点是: 配置和代码是分离的,在 xml 中做修改,无需编译代码,只需重启服务器即可将新的配置加载。
- xml 的缺点是:编写麻烦,效率低,大型项目过于复杂。
Spring JDBC
Spring 是一个一站式框架:Spring自身也提供了控制层的SpringMVC和持久层的Spring JdbcTemplate.
1.下载Spring JdbcTemplate的包
<!-- 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.创建一个config.properties文件
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/数据库名?serverTimezone=Asia/Shanghai
uname=root//数据库账号
pwd=root//数据库密码
3.在spring配置文件中导入
<context:property-placeholder location="config.properties"/>
4.在db.xml中管理数据源对象
<!--spring统一管理数据库连接对象-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${driver}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${uname}"></property>
<property name="password" value="${pwd}"></property>
<property name="initialSize" value="5"></property>
<property name="maxActive" value="10"></property>
</bean>
5.在db.xml中创建 JdbcTemplate
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
6.在Dao层获得 JdbcTemplate对象
execute:无返回值,可执行 ddl,增删改语句
update:执行新增、修改、删除语句;
queryForXXX:执行查询相关语句;
AOP开发思想:开发好一个版本后,后期需要添加新的功能,就需要改变原来的代码,加入调用新功能的代码,开发麻烦,会存在大量的冗余的代码
AOP是一种编程技巧,不是代替OOP,可以使业务逻辑和非业务逻辑进行隔离,使得各个部分之间的耦合度降低,提高程序的复用性,提高了开发效率
AOP
Aop:将程序中的一些非业务逻辑代码进行提取,在不需要修改原来代码情况,为程序添加额外的功能,非业务逻辑代码(验证权限 打印日志 提交事务 统一异常处理)
实现的方法:是通过一个代理对象,告诉代理对象,调用哪个方法时,让代理对象去帮助我们代用哪个方法(AdminDao->生成一个代理对象)底层:动态代理模式
AOP并不是Spring框架中特有的,只是Spring框架引入这一思想
Aop的基本概念:
- 连接点:类中可以被增强的方法,称为连接点
- 切入点:类中实际被增强的方法,称为切入点(横切面切入的方法)
- 通知:提取得非业务的功能称为通知
- 切面:把通知添加到切入点的过程
- 目标:代理的目标对象
- 代理:向目标对象应用通知创建的代理对象
AspectJ 是一个基于 Java 语言的 AOP 框架,它提供了强大的 AOP 功能,且其实
现方式更为简捷,使用更为方便, 而且还支持注解式开发。配置步骤如下:
1.下载相关的Jar包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
2.基于aspectj的xml配置方式实现
<bean id="aopdemo" class="com.ff.spring.aop.AopDemo"></bean>
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(*
com.ff.spring.service.UserService.adduser(..))" id="adduser"/>
<aop:pointcut expression="execution(*
com.ff.spring.service.UserService.*(..))" id="allmethod"/>
<!-- 配置通知和切入点 -->
<aop:aspect ref="aopdemo">
<aop:before method="savelog" pointcut-ref="adduser"/>
<aop:after method="savelog" pointcut-ref="adduser"/>
<aop:around method="aroundAdvice" pointcut-ref="adduser"/>
<aop:after-throwing method="exceptionAdvice" pointcut-ref="allmethod"
throwing="e" />
</aop:aspect>
</aop:config>
该通知有五种:
- 前置通知:方法执行前调用
- 后置调用:业务方法执行后调用,当方法出现异常后不执行
- 异常通知:业务方法出现异常时调用
- 最终通知:业务方法执行后调用,当方法出现异常时也会调用
- 环绕通知
<aop:config>
<!--配置切入点-->
<aop:pointcut id="saveAdmin" expression="execution(* com.ffyc.ssm.dao.AdminDao.saveAdmin(..))"/>
<!--将通知与切入点进行配置,生成的代理对象就知道如何调用-->
<aop:aspect ref="myutil">
<!-- <aop:before method="printLog" pointcut-ref="saveAdmin"></aop:before>-->
<!-- <aop:after-returning method="printLog" pointcut-ref="saveAdmin"></aop:after-returning>-->
<!-- <aop:after method="printLog" pointcut-ref="saveAdmin"></aop:after>-->
<!-- <aop:after-throwing method="exceptionAdvice" pointcut-ref="saveAdmin" throwing="e"></aop:after-throwing>-->
<aop:around method="aroundAdvice" pointcut-ref="saveAdmin"></aop:around>
</aop:aspect>
</aop:config>
基于注解方式实现
@Component//让spring管理生成对象
@Aspect//启动Aspect 开启自动代理 表面装有通知的类/切面
public class MyUtil {
// @Before("execution(* com.ffyc.ssm.dao.AdminDao.saveAdmin(..))")
// public void printLog(){
// System.out.println("打印日志");
// }
//
// public void commit(){
// System.out.println("事务提交");
// }
// @AfterThrowing(value="execution(* com.ffyc.ssm.dao.AdminDao.saveAdmin(..))",throwing = "e")
// public void exceptionAdvice(Throwable e){
// System.out.println("异常通知"+e.getMessage());
// }
//@Around("execution(* com.ffyc.ssm.dao.AdminDao.saveAdmin(..))")
public void aroundAdvice(ProceedingJoinPoint point){
try {
System.out.println("前置通知");
point.proceed();
System.out.println("后置通知");
} catch (Throwable throwable) {
// throwable.printStackTrace();
// System.out.println("异常通知");
}
System.out.println("最终通知");
}
}
Spring事务管理
什么是数据库事务?
spring框架里面提供了事务管理的功能,事务管理是数据库提供佛仍一种功能,为了保证了数据在过程在过程中的准确性,事务管理是管理一组中有多个执行单元,一个事务就是一个单元,一个单元可以包含很多个SQL语句。
关系型数据库的基本特征:
- 原子性特征(一次操作中的多条SQL语句,要么都执行,要么都不执行)
- 隔离性
- 持久性
- 一致性
Spring中事务管理有两种:
1.编程式事务管理-->在代码中自己写
2.声明式事务管理-->使用注解标签实现(底层思想是AOP思想,是方法级别的,在执行某个方法中,为方法添加额外的事务管理功能)
@Transactional标签的用法:
- 一般把@Transactional标签添加在service中
- @Transactional可以添加在service层中类上,类中的所有方法都会添加事务
- @Transactional如果值添加到方法上,表示此方法在事务管理进行
以下6种情况@Transactional不会生效:
- @Transactional应用在非public修饰的方法上(底层针对public修饰的方法)
- 方法中异常被catch捕获处理
- 编译器异常(事务不生效,默认情况下只对运行期异常进行捕获 rollbackFor=Expection.class 任何异常都能捕获)
- @Transactional事务传播行为设置错误
- 数据库引擎不支持事务(数据库引擎是mysql底层具体的一种数据处理实现的机制 常用的两个引擎 innodb(支持事务) myisam(不支持事务))
- 同一个类中,使用非代理对象调用增强方法,用this调方法表示自己没有被进行任何加强