文章内容输出来源:拉勾教育Java就业急训营
Spring是什么
Spring是分层的 Java SE/EE应用 full-stack(全栈式) 轻量级开源框架。
提供了表现层 SpringMVC和持久层 Spring JDBC Template以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的Java EE 企业应用开源框架。
两大核心:以 IOC(Inverse Of Control:控制反转)和 AOP(Aspect Oriented Programming:面向切面编程)为内核。
Spring的优势
1)方便解耦,简化开发
Spring就是一个容器,可以将所有对象创建和关系维护交给Spring管理 什么是耦合度?
对象之间的关系,通常说当一个模块(对象)更改时也需要更改其他模块(对象),这就是耦合,耦合度过高会使代码的维护成本增加。
要尽量解耦。
2)AOP编程的支持 Spring提供面向切面编程,方便实现程序进行权限拦截,运行监控等功能。
3)声明式事务的支持 通过配置完成事务的管理,无需手动编程
4)方便测试,降低JavaEE API的使用
Spring对Junit4支持,可以使用注解测试
5)方便集成各种优秀框架 不排除各种优秀的开源框架,内部提供了对各种优秀框架的直接支持
IOC
控制反转(Inverse Of Control)不是什么技术,而是一种设计思想。它的目的是指导我们设计出更
加松耦合的程序
控制:在java中指的是对象的控制权限(创建、销毁)
反转:指的是对象控制权由原来 由开发者在类中手动控制 反转到 由Spring容器控制
例子
- 传统方式 之前我们需要一个userDao实例,需要开发者自己手动创建 new UserDao();
- IOC方式 现在我们需要一个userDao实例,直接从spring的IOC容器获得,对象的创建权交给了spring控制
IOC快速入门
步骤
- 创建java项目,导入spring开发基本坐标
- 编写Dao接口和实现类
- 创建spring核心配置文件
- 在spring配置文件中配置 UserDaoImpl
- 使用spring相关API获得Bean实例
- 导入依赖
org.springframework
spring-context
5.1.5.RELEASE
junit
junit
4.12
- 编写接口和实现类
public interface UserDao {
public void save();
}
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("保存成功了...");
}
}
- 创建核心配置文件
- 在spring配置文件中配置 UserDaoImpl
- 使用spring相关API获得Bean实例
public class TestSpring {
@Test
public void test() {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) classPathXmlApplicationContext.getBean("userDao");
userDao.save();
}
}
重点关注BeanFactory 和 ApplicationContext
BeanFactory
BeanFactory是 IOC 容器的核心接口,它定义了IOC的基本功能。
特点:在第一次调用getBean()方法时,创建指定对象的实例
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
beanFactory.getBean();
ApplicationContext
代表应用上下文对象,可以获得spring中IOC容器的Bean对象。
特点:在spring容器启动时,加载并创建所有对象的实例
ApplicationContext ac =new ClassPathXmlApplicationContext("applicationContext.xml");
ac.getBean()
Spring配置文件
- Bean标签基本配置
* 用于配置对象交由Spring来创建。
* 基本属性: id:Bean实例在Spring容器中的唯一标识 class:Bean的全限定名
* 默认情况下它调用的是类中的 无参构造函数,如果没有无参构造函数则不能创建成功。
- Bean标签范围配置
scope属性指对象的作用范围,取值如下:
取值范围 | 说明 |
---|---|
singleton | 默认值,单例的 |
prototype | 多例的 |
request | WEB项目中,Spring创建一个Bean的对象,将对象存入到request域中 |
session | WEB项目中,Spring创建一个Bean的对象,将对象存入到session域中 |
global session | WEB项目中,应用在Portlet环境,如果没有Portlet环境那么globalSession 相当于 session |
1. 当scope的取值为singleton时
Bean的实例化个数:1个
Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例
Bean的生命周期: 对象创建:当应用加载,创建容器时,对象就被创建了
对象运行:只要容器在,对象一直活着
对象销毁:当应用卸载,销毁容器时,对象就被销毁了
2. 当scope的取值为prototype时 Bean的实例化个数:多个
Bean的实例化时机:当调用getBean()方法时实例化Bean
Bean的生命周期: 对象创建:当使用对象时,创建新的对象实例
对象运行:只要对象在使用中,就一直活着
对象销毁:当对象长时间不用时,被 Java 的垃圾回收器回收了
- Bean生命周期配置
* init-method:指定类中的初始化方法名称
* destroy-method:指定类中销毁方法名称
- Bean实例化三种方式
- 无参构造方法实例化
- 工厂静态方法实例化
- 工厂普通方法实例化
DI
依赖注入 DI(Dependency Injection):它是 Spring 框架核心 IOC 的具体实现。
在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是代码中不可能出现没有依赖的情
况。IOC 解耦只是降低他们的依赖关系,但不会消除。例如:业务层仍会调用持久层的方法。
那这种业务层和持久层的依赖关系,在使用 Spring 之后,就让 Spring 来维护了。简单的说,就是通
过框架把持久层对象传入业务层,而不用我们自己去获取。
Bean依赖注入方式
- 构造器注入 (要求JavaBean有相应的构造方法)
- set方法注入
- p命名空间注入
本质也是set方法注入
先引入p命名空间xmlns:p="http://www.springframework.org/schema/p"
标签知识小节
标签:创建对象并放到spring的IOC容器
id属性:在容器中Bean实例的唯一标识,不允许重复
class属性:要实例化的Bean的全限定名
scope属性:Bean的作用范围,常用是Singleton(默认)和prototype
标签:属性注入
name属性:属性名称
value属性:注入的普通属性值
ref属性:注入的对象引用值
标签:属性注入
name属性:属性名称
value属性:注入的普通属性值
ref属性:注入的对象引用值
注解开发
注解 | 说明 |
---|---|
@Component | 使用在类上用于实例化Bean |
@Controller | 使用在web层类上用于实例化Bean |
@Service | 使用在service层类上用于实例化Bean |
@Repository | 使用在dao层类上用于实例化Bean |
@Autowired | 使用在字段上用于根据类型依赖注入 |
@Qualifier | 结合@Autowired一起使用,根据名称进行依赖注入 |
@Resource | 相当于@Autowired+@Qualifier,按照名称进行注入 |
@Value | 注入普通属性 |
@Scope | 标注Bean的作用范围 |
@PostConstruct | 使用在方法上标注该方法是Bean的初始化方法 |
@PreDestroy | 使用在方法上标注该方法是Bean的销毁方法 |
AOP
什么是AOP
AOP 为 Aspect Oriented Programming 的缩写,意思为面向切面编程。
AOP 是 OOP(面向对象编程)的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP优点
- 在程序运行期间,在不修改源码的情况下对方法进行功能增强
- 逻辑清晰,开发核心业务的时候,不必关注增强业务的代码
- 减少重复代码,提高开发效率,便于后期维护
AOP底层实现
实际上,AOP 的底层是通过 Spring提供的的动态代理技术实现的。在运行期间,Spring通过动态代
理技术动态的生成代理对象,代理对象方法执行时进行增强功能的介入,在去调用目标对象的方法,从而完成功能的增强。
在 Spring中,框架会根据目标类是否实现了接口来决定采用哪种动态代理的方式。
当bean实现接口时,会用JDK代理模式
当bean没有实现接口,用cglib实现(可以强制使用cglib(在spring配置中加入
AOP相关术语
* Target(目标对象):代理的目标对象
* Proxy(代理):一个类被 AOP 织入增强后,就产生一个结果代理类
* Joinpoint(连接点):所谓连接点是指那些可以被拦截到的点。在spring中,这些点指的是方法,因为 spring只支持方法类型的连接点
* Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义
* Advice(通知/ 增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知
分类:前置通知、后置通知、异常通知、最终通知、环绕通知
* Aspect(切面):是切入点和通知(引介)的结合
* Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入。
AOP快速入门
步骤
- 创建java项目,导入AOP相关坐标
- 创建目标接口和目标实现类(定义切入点)
- 创建通知类及方法(定义通知)
- 将目标类和通知类对象创建权交给spring
- 在核心配置文件中配置织入关系,及切面
- 编写测试代码
- 导入AOP依赖
org.springframework
spring-context
5.1.5.RELEASE
org.aspectj
aspectjweaver
1.8.13
org.springframework
spring-test
5.1.5.RELEASE
junit
junit
4.12
- 创建切入点
public class Targer {
public void transfer() {
System.out.println("转账业务...");
}
}
- 创建通知类和通知方法
public class MyAdvice {
public void before() {
System.out.println("before...");
}
}
- 将目标类和通知类对象创建权交给spring
- 在核心配置文件中配置织入关系,及切面
导入aop命名空间
- 编写测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
class AOPTest {
@Autowired private Target target;
@Test public void testTransfer() throws Exception {
target.transfer();
}
}
XML配置AOP详解
切点表达式
execution([修饰符] 返回值类型 包名.类名.方法名(参数))
- 访问修饰符可以省略
- 返回值类型、包名、类名、方法名可以使用星号 * 代替,代表任意
- 包名与类名之间一个点 . 代表当前包下的类,两个点 ..
- 表示当前包及其子包下的类
- 参数列表可以使用两个点 .. 表示任意个数,任意类型的参数列表
通知类型
header 1 | header 2 |
---|---|
row 1 col 1 | row 1 col 2 |
row 2 col 1 | row 2 col 2 |
名称 | 标签 | 说明 |
---|---|---|
前置通知 | 用于配置前置通知。指定增强的方法在切入点方法之前执行 | |
后置通知 | 用于配置后置通知。指定增强的方法在切入点方法之后执行 | |
异常通知 | 用于配置异常通知。指定增强的方法出现异常后执行 | |
最终通知 | 用于配置最终通知。无论切入点方法执行时是否有异常,都会执行 | |
环绕通知 | 用于配置环绕通知。开发者可以手动控制增强代码在什么时候执行 |
注意:通常情况下,环绕通知都是独立使用的
基于注解配置AOP
- 通知类
@Aspect
@Component
public class MyAspect {
@Before("execution(* com.lagou..*.*(..))")
public void before() {
System.out.println("before...");
}
}
- 在配置文件中开启组件扫描和 AOP 的自动代理
JdbcTemplate
JdbcTemplate是spring框架中提供的一个模板对象,是对原始繁琐的Jdbc API对象的简单封装。
核心对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(DataSource dataSource);
核心方法
int update(); 执行增、删、改语句
List query(); 查询多个
T queryForObject(); 查询一个
new BeanPropertyRowMapper<>(); 实现ORM映射封装
- 编写spring配置文件
事务控制
Spring的事务控制可以分为编程式事务控制和声明式事务控制。
编程式
开发者直接把事务的代码和业务代码耦合到一起,在实际开发中不用。
声明式
开发者采用配置的方式来实现的事务控制,业务代码与事务代码实现解耦合,使用的AOP思想。
事务隔离级别
设置隔离级别,可以解决事务并发产生的问题,如脏读、不可重复读和虚读(幻读)。
* ISOLATION_DEFAULT 使用数据库默认级别
* ISOLATION_READ_UNCOMMITTED 读未提交
* ISOLATION_READ_COMMITTED 读已提交
* ISOLATION_REPEATABLE_READ 可重复读
* ISOLATION_SERIALIZABLE 串行化
事务传播行为
事务传播行为指的就是当一个业务方法【被】另一个业务方法调用时,应该如何进行事务控制。
基于XML的声明式事务控制
在 Spring 配置文件中声明式的处理事务来代替代码式的处理事务。底层采用AOP思想来实现的。
声明式事务控制明确事项:
- 核心业务代码(目标对象) (切入点是谁?)
- 事务增强代码(Spring已提供事务管理器))(通知是谁?)
- 切面配置(切面如何配置?)
步骤
- 引入tx命名空间
- 事务管理器通知配置
- 事务管理器AOP配置
- 测试事务控制转账业务代码
- 引入tx命名空间
- 事务管理器通知配置
- 事务管理器AOP配置
- 测试事务控制转账业务代码
@Override
public void transfer(String outUser, String inUser, Double money) {
accountDao.out(outUser, money);
// 制造异常
int i = 1 / 0;
accountDao.in(inUser, money);
}
事务参数的配置详解
* name:切点方法名称
* isolation:事务的隔离级别
* propogation:事务的传播行为
* timeout:超时时间
* read-only:是否只读
基于注解的声明式事务控制
常用注解
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ, timeout = -1, readOnly = false)可以加在方法上或者类上
编写配置文件