目录
Spring概述
Spring是2003年兴起的一个轻量级的,IOC和AOP的Java开发框架,为了简化企业级的开发。
轻量级:Spring使用的jar都比较小,在运行时占用的资源少且运行效率高。
IOC(Inversion of Control):控制反转。就是将项目中创建的对象统一交给Spring IOC容器来管理对象,还可以额外的对对象进行功能的添加,需要时直接从框架获取即可,也就是把创建对象的控制权反转给Spring框架。
AOP(Aspect Object Programming):面向切面编程。它是OOP(面向对象编程)的补充。面向对象编程将程序抽象成各个层次的对象,而面向切脉你编程是将程序抽象成各个切面。将程序中的一些公共功能进行抽取,不需要我们在自己的方法中直接显示的调用,而是由代理对象去调用,然后在调用我们的方法时可以将公共的方法横切进来。
一站式框架:Spring的核心是统一管理程序中的对象(IOC),它还提供了AOP,还对数据访问层和web层进行了封装,还可以很方便的集成其它框架和组件。
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搭建
Maven导入Spring核心基础jar
<!-- spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
编写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>
编写实体类
以User类为例
public class User{
private String name;
private int age;
public void work(){
System.out.println(this.name + "工作");
}
}
测试Spring
public class Test{
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
User user1 = applicationContext.getBean("user",User.class);
User user2 = applicationContext.getBean("user",User.class);
System.out.println(user1);
System.out.println(user1);
}
}
IOC(控制反转)
IOC(Inversion of Control)控制反转,是一种设计思想,就是将在程序中创建对象的控制权反转给Spring框架统一管理。
IOC容器是具有依赖注入功能的容器,负责对象的实例化、对象的初始化、对象和对象之间依赖关系配置、对象的销毁、对外提供对象的查找等操作,对象的整个生命周期都是由容器来控制。我们使用的对象都由IOC容器进行统一管理,不需要我们手动通过new的方式创建对象,需要用的时候直接从IOC容器中获取。
@Test
public void test1(){
/*
ClassPathXmlApplicationContext("配置文件") 负责具体对象管理的实现类
ApplicationContext 接口 是beanFactory的子接口,扩展一些其他的功能
beanFactory 接口 是spring框架中最顶级的接口定义了基本的对象管理的方法
*/
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
User user = applicationContext.getBean("user",User.class);//通过bean的标识,从spring容器中获得到bean
System.out.println(user);
User user2 = applicationContext.getBean("user2",User.class);
System.out.println(user2);
}
底层实现方式:解析xml/扫描注解标签 + 工厂模式 + 反射机制
Spring Bean管理
基于xml配置方式
在bean标签中配置需要让Spring框架进行管理的类,由Spring框架创建管理的兑现,一般 称为一个bean对象,自己new的对象称为原生对象。
<?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标签中配置需要让spring框架进行管理的类
由spring框架创建管理的对象,一般称为一个bean对象,自己new的对象称为原生对象
id="唯一标识"
name = "也可以用name作为标识(别名)"
class="类地址"
scope="singleton" bean的作用域
singleton单例bean,始终只会创建一个bean对象,在容器启动种创建
prototype 原型的(多例的) 每次getBean()时,都会创建一个新的bean对象,在每次获取时创建
-->
<bean id="user" name="user2" class="com.ffyc.springpro.model.User" scope="prototype"</bean>
</beans>
Xml配置方式依赖注入
DI(Dependency Injection):指Spring创建对象的过程中,对象中有属性(简单值,集合,对象),Spring为这些属性进行赋值的过程称为依赖注入。
依赖注入一般与控制反转是伴随发生的。
注入方式:set方法注入和构造方法注入
<!--
spring为我们创建对象时,需要为对象中的属性进行赋值操作(依赖注入)
注入可以通过属性的set方法和构造方法
-->
<!--set方法注入-->
<bean id="user" name="user2" class="com.ffyc.springpro.model.User" scope="prototype">
<property name="id" value="100"></property>
<property name="name" value="jim"></property>
</bean>
<!--构造方法注入-->
<bean id="user" class="com.ffyc.springpro.model.User" scope="prototype">
<constructor-arg name="id" value="100"></constructor-arg>
<constructor-arg name="name" value="jim"></constructor-arg>
</bean>
<!--
对对象中关联的其他对象进行依赖注入
首先将对象中关联的对象用bean标签交给Spring框架统一管理,然后在进行依赖注入
ref="userDao" 与bean标签中的id互相绑定
-->
<bean id="userDao" class="com.ffyc.springpro.dao.UserDao"></bean>
<bean id="userService" class="com.ffyc.springpro.service.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
注解方式实现
添加注解标签前,先需要将注解需要的jar包导入。
开启注解扫描
<context:component-scan base-package="包名"> </context:component-scan>
注解创建对象
//注解标签等同于xml中的<bean></bean>
@Component(value = "user")
@Scope(value = "prototype")
public class User{}
//是给service层提供的注解标签
@Service
public class UserService{}
//是给dao层提供的注解标签
@Repository
public class UserDap{}
注解方式注入属性 DI
@Autowired可以为属性自动注入值,可以添加在属性上,也可以添加在set方法上,这个注解标签是spring框架提供的。添加到属性上,可以不需要set方法,但默认值不能为空。该注解默认使用按类型自动装配bean的方式,但如果我们想使用按照名称来装配,可以结合@Qualifier 注解一起使用。
@Resource是jdk提供的,可以通过名字查找,也可以通过类型查找。默认按照名字查找。
注解与XML对比
注解优点:方便,直观,高效(代码少,没有配置文件书写那么复杂)
注解缺点:以硬编码的方式写入到Java代码中,修改需要重新编译代码
XML优点:配置和代码是分离的,在xml中修改,不需要编译代码,只需重启服务器即可。
XML缺点:编写麻烦,效率低,大型项目过于复杂
Spring JDBC
Spring是一个一站式框架,它自身也提供了Spring WEB 和持久层的Spring JdbcTemplate。
1.下载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>
2.导入属性文件
<context:property-placeholder location="config.properties"/>
3.管理数据源对象
<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>
4.在配置文件中创建JdbcTemplate
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
在类中获得JdbcTemplate对象,就可以直接使用
@Autowired
JdbcTemplate jdbcTemplate;
JdbcTemplate中常用的方法
execute:无返回值,可执行ddl,增删改语句
update:执行新增、修改、删除语句
queryForXXX:执行查询相关语句
AOP概述
AOP(Aspect Oriented Programming)面向切面编程,OOP是面向对象编程,AOP可以看作是OOP的补充。AOP是将程序中的非业务代码进行抽取,将业务代码和非业务代码进行隔离,降低耦合度,然后通过一个代理对象在业务代码中调用非业务代码,提高代码的灵活性。
AOP、OOP在字面上虽然非常相似,但却是面向不同领域的两种设计思想。
面向切面编程的好处就是减少重复,专注业务。
核心原理:使用动态代理的方式在执行方法前后或者出现异常的时候加入相关的逻辑。
AOP基本概念
连接点(JoinPoint):类中可以被增强的方法,这个方法就被称为连接点。
切入点(PointCut):类中实际被增强的方法(实际实现的连接点)。
通知(Advice):指连接点(方法)被增强的功能。通知又分为前置通知、后置通知、异常通知、最终通知、环绕通知。
切面(Aspect):把通知添加到切入点的过程。
目标(Target):代理的目标对象。
代理(Proxy):向目标对象应用通知时创建的对象。
Spring AOP实现
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配置方式实现
<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>
AspectJ中常用的通知有五种类型:前置通知、后置通知、异常通知、最终通知、环绕通知。
//五种通知
public void beforeAdvice(){
System.out.println("前置通知");
}
public void afterReturningAdvice(){
System.out.println("后置通知");
}
public void ExcetionAdvice(Throwable e){
System.out.println("异常通知" + e.getMessage());
}
public void afterAdvice(ProceddingJoinPoint proceddingJoinPoint){
System.out.println("最终通知");
try{
proceddingJoinPoint.proceed();//调用方法
}catch(Throwable e){
e.printStackTrace();
}
System.out.println("方法之后通知");
}
public void aroundAdvice(){
System.out.println("方法之前通知");
基于注解方式的实现
启动AspectJ支持: <aop:aspectj-autoproxy />
@Around(value = "execution(* com.ffyc.springpro.dao.AdminDao.*(..))")
public void savaLog(ProceedingJoinPoint proceedingJoinPoint){
try {
System.out.println("前置通知");
proceedingJoinPoint.getArgs();//获取参数
proceedingJoinPoint.proceed();
System.out.println("后置通知");
}catch (Throwable e){
System.out.println("异常通知"+e.getMessage());
}
System.out.println("最终通知");
}
@Before("execution(* com.ffyc.springpro.dao.AdminDao.*(..))")
public void savaLog(Throwable e){
System.out.println("保存时间:"+new Date()+e.getMessage());
}
@After("execution(* com.ffyc.springpro.dao.AdminDao.*(..))")
public void savaLog(Throwable e){
System.out.println("保存时间:"+new Date()+e.getMessage());
}
@AfterReturning("execution(* com.ffyc.springpro.dao.AdminDao.*(..))")
public void savaLog(Throwable e){
System.out.println("保存时间:"+new Date()+e.getMessage());
}
@AfterThrowing(value = "execution(* com.ffyc.springpro.dao.AdminDao.*(..))",throwing = "e")
public void savaLog(Throwable e){
System.out.println("保存时间:"+new Date()+e.getMessage());
}
Spring事务管理
事务:数据库事务,是属于数据库中的功能,可以看做是若干个对数据库的操作组成的一个单元。Spring事务管理的底层使用的就是AOP思想。
比如,一次对数据库操作的整个过程管理,一次对数据库操作时,可能会有很多条sql语句需要执行,数据库为了保证数据的完整性,让一次操作中的多条sql要么都执行成功,要么都失败。最经典的案例就是银行转账。
Spring事务管理只是为我们自动的提交或回滚事务,可以把这部分代码进行封装。
Spring事务管理分为两种:编程式事务和声明式事务。
编程式事务
在项目中很少使用,需要手动的在代码中进行提交或回滚。
声明式事务
Spring声明式事务管理方式有两种:基于xml配置和基于注解实现。
Spring针对不同的dao框架,提供了不同的实现类,Jdbc,mybatis事务管理实现类是DataSourceTransactionManager
配置事务管理器
<!-- 配置 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
@Transactional
声明式事务不生效的场景
- @Transactional应用在非public修饰的方法上
- 异常被catch捕获导致失效
- 出现编译期异常
- @Transactional事务传播行为设置错误
- 数据库引擎不支持事务
- 同一个类中,使用非代理对象调用一个有事物的方法,导致事务错误
Spring事务传播行为
事务传播行为(propagation behavior)指的是当一个事务方法被另一个事务方法调用时,这个事务方法该如何进行。例如A方法调用B方法,那么B方法是创建一个新事物还是加入到A方法的事务中运行。事务传播行为是Spring框架独有的控制机制,它不属于事务实际提供数据库行为。
Spring定义了七种传播行为
- PROPAGATION_REQUIRED 指定的方法必须在事务内执行,若当前存在事务就加入到当前事务,若当前没有事务,就创建一个新事物,这种传播行为也是最常见的,也是Spring默认的传播行为。
-
PROPAGATION_SUPPORTS 支持当前事务,如果当前有事务,就加入当前事务,如果当前没有事务,就以非事务方式执行。
-
PROPAGATION_REQUIRES_NEW 总是新建一个事务,如果当前存在事务,就把当前事务挂起,知道新创建的事务结束。
Spring集成Mybatis
Spring集成mybatis核心是把SqlSessionFactory交给Spring管理,并由Spring管理对dao接口的代理实现。
导入Spring结合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>