Spring
Spirng基础
- 什么是Spring?
Spring是一个开源的轻量级框架,它由Rod Johnson创建。 - Spring的优点
方便解耦,简化开发。 - eclipse安装spring插件
IOC
控制反转
- 创建对象的权利由开发人员new交给Spring容器。
- 测试
- 创建maven项目
- 添加依赖jar包
<dependencies>
<!--webmvc会将spring需要的jar包都导入-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.9.RELEASE</version>
</dependency>
<!-- 测试jar包 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
3. 配置applicationContext.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 class="com.shyb.Student" id="student"></bean>
</beans>
package com.shyb;
public class Student {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
DI
- Dependency injection 依赖注入
- 依赖
一个对象需要使用另一个对象 - 注入
通过setter或构造方法对另一个对象实例设置。 - 示例
UserService userService = new UserService(); -->IOC
UserDao userDao = new UserDao(); -->IOC
userService.setUserDao(userDao); -->DI
核心API
- BeanFactory
生产Bean的工厂(延迟加载对象,getBean时实例化 xml) - ApplicationContext
BeanFactory的子接口,功能更强大。
当配置文件被加载时(项目启动时),对象就进行了实例化(调构造方法)。
实现类:- ClassPathXmlApplicationContext
用于加载classpath下的xml(WEB-INF/classes/…xml),配置在resources下需写classpath:…xml - FileSystemXmlApplicationContext(不常用)
加载WEB-INF/…xml时,用ServletContext.getRealPath()获取盘符
- ClassPathXmlApplicationContext
装配Bean
- bean的实例化方式
基于XML
- 默认构造
<!-- 采用默认构造方法生产 没有默认构造方法报错--> <bean id="" class=""></bean>
- 静态工厂
常用于Spring整合其他框架和工具的
<bean id="" class="" factory-method=""></bean>
3. 实例工厂
通过工厂对象创建对象
setter方法注入
两种注入方式
p命名空间注入(了解)
对setter注入进行简化,替换properties标签
SpEl注入(了解)
对properties进行统一编程,所有内容统一使用value
value="#{}" 写el表达式
常量:#{13} #{“张三”}
引用:#{car} #{car.name
}
方法:#{car.toString()}
静态:#{T(java.lang.Math).PI}
集合注入
生成get set和toString方法
构造方法注入
基于注解
使用注解取代xml配置文件(加快开发速度)。
需要添加context并扫描注解所在的包
常见注解
- @Component
取代<bean class="">
,@Component(“userService”)取代<bean id="userService" class="">
<context:component-scan base-package="com.shyb.service"/>
扫描添加注解的类所在的包 - Web开发
@Component衍生注解(功能和@Component一样)- @Repository
- @Service
- @Controller
- 依赖注入
- 普通值:@Value("")
- 引用值:
- 按照类型注入(接口有两个实现类时,难以区分)
@Autowired - 按照名称注入
@Autowired
@Qualifer(“名称”)
或者@Resource(“名称”)
- 按照类型注入(接口有两个实现类时,难以区分)
- 生命周期
初始化:@PostConstruct
销毁:@PreDestroy - 作用域
@Scope(“prototype”)
Bean的种类
- 普通bean
直接通过bean标签的id获取对象 - FactoryBean
通过bean标签的id获取FactoryBean对象,调用getObject方法,返回对象
作用域
- Singleton单例
- prototype多例
<!--默认是单例的 scope="prototype"配置多例 -->
<bean id="userService" class="com.shyb.service.impl.UserServiceImpl" scope="prototype"></bean>
生命周期
- 初始化和销毁
目标方法执行前执行后执行,只执行一次(单例情况下)
<bean id="userService" class="com.shyb.service.impl.UserServiceImpl" init-method="init" destroy-method="destory"></bean>
2. BeanPostProcessor后处理Bean
Spring提供了一种机制,只要实现接口BeanPostProcessor,并将实现类提供给spring容器,在spring初始化方法前会执行before()方法,后执行after()方法。
流程:
A a = new A();
a = B.before(a); 返回Null后续就会报NPE
a.init();
a = B.after(a);
a.addUser();
a.destory();
AOP
AOP(面向切面编程)
AOP介绍
- AOP实现原理
底层采用代理机制实现。在运行期间通过代理向目标类植入增强代码。
接口加实现类:spring采用jdk的动态代理
父类和实现类:cglib代理 - 经典应用
事务代理、性能监视、安全检查、缓存、日志等。 - AOP术语
- target 目标类(需要被代理的类)
- Joinpoint(连接点) 指可能被拦截到的方法。一般指所有方法
- PointCut(切入点) 已经被增强的连接点。
- advice 通知/增强
- Weaving织入 把advice应用到target创建proxy的过程
- proxy代理类
- Aspecj 切面 PointCut和advice的结合
AOP代理
-
手动实现
- JDK动态代理
- 目标类:接口+实现类
- 切面类:存放advice
- 工厂类:编写工厂生产代理
- cglib
运行期间创建目标类的子类,从而对目标类进行增强。
- JDK动态代理
-
AOP通知类型
- 前置通知[Before advice]:在连接点前面执行,前置通知不会影响连接点的执行,除非此处抛出异常。
- 正常返回通知[After returning advice]:在连接点正常执行完成后执行,如果连接点抛出异常,则不会执行。
- 异常返回通知[After throwing advice]:在连接点抛出异常后执行。
- 返回通知[After (finally) advice]:在连接点执行完成后执行,不管是正常执行完成,还是抛出异常,都会执行 返回通知中的内容。
- 环绕通知[Around advice]:环绕通知围绕在连接点前后,比如一个方法调用的前后。这是最强大的通知类 型,能在方法调用前后自定义一些操作。环绕通知还需要负责决定是继续处理join point(调用ProceedingJoinPoint 的proceed方法)还是中断执行。
-
aop全自动
- 从spring中获取目标类,如果配置aop,spring自动生成代理
- 要确认目标类,aspectj切入点表达式
- 添加依赖
<!-- aop依赖jar包 --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.13</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.13</version> </dependency>
- 添加扫描文件
AspectJ
- AspectJ是基于Java语言的AOP框架
- 支持注解开发
切入点表达式:
示例1:execution(* com.shyb..*.*(..))
com.shyb的包及子包中所有方法
实例2:execution(* com.shyb.service.*.add*(..))
所有service下所有类的add方法 - AspectJ通知类型
AOP联盟定义了通知类型,具有特定接口,必须实现,从而确定方法名称
通知类型:
1. before(校验参数)
2. afterReturning(常规数据处理)
3. around(功能强大,可以做任何事)必须手动执行方法
4. afterThrowing
5. after(释放资源)
AspectJ xml开发配置
- 目标类:接口+实现类
- 通知类:方法名任意
AspectJ 注解开发配置
事务管理
事务介绍
- 事务:一组业务,要么同时成功,要么同时失败。
- 特性:ACID
- 原子性
事务是最小的工作单元,不可拆分。 - 一致性
同时完成,同时失败。 - 隔离性
并发,事务之间要互相隔离,互不影响 - 持久性
事务一旦提交,对数据库的改变是永久性的。
- 原子性
- 隔离问题
- 脏读
一个事务读到另一个事务没有提交的数据 - 不可重复读
一个事务读到另一个事务已提交的数据(update) - 幻读
一个事务读到另一个事务已提交的数据(insert)
- 脏读
- 隔离级别
- read uncommited 读未提交
存在三个问题 - read commited 读已提交
解决脏读 - repeatable read 可重复读
解决可重复读 - serializable 串行化
都解决(执行的是单事务,相当于单线程)
- read uncommited 读未提交
Spring使用事务
- Spring要使用事务,必须使用事务管理器
- 配置事务详情(隔离级别,只读,超时时间等)
- 事务状态 记录事务的状态(是否有保存点,是否已完成),Spring自己完成,不需要操作
- 传播行为 两个业务之间如何共享事务
- 导入Jar包
<!-- spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.9.RELEASE</version>
</dependency>
<!-- mysql数据库的依赖jar包 -->
<dependency>
<groupId>MySQL</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
基于xml配置
xmlns:tx="http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
也可以使用*
基于注解配置
- 配置事务管理器,并将其交给Spring
- 在目标类或方法添加注解@Transactiona
整合Junit
- 导入spring-test jar包
<dependency>
<groupId>com.arakelian</groupId>
<artifactId>spring-test-utils</artifactId>
<version>1.0.2</version>
<type>pom</type>
</dependency>
- 配置测试
整合Web
- 导入spring-web jar包
spring-mvc pom文件会自动依赖导入 - 配置web-xml
<!--监听器启动加载spring配置--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param>