IOC

什么是IOC?如果你回答:Spring是个IOC容器,实现原理是反射,没了。这样证明你没有真正理解IOC。

IOC的意思是控制反转,还有个外号叫依赖注入(DI)。为什么起这么晦涩难懂的名字呢?

首先,我们看没有Spring之前,是怎么写代码的。

class SomeController{

    // 传统的new一个对象的方式
private SomeService service = new SomeServiceImpl(); public String doSomeThing(){
return service.getSomeThing();
}
}

这种有什么缺点呢?

1. 这个类直接依赖于另一个类的实现(代码耦合)。

2. 如果未来发生了变动,比如变成另一种实现 SomeServiceImplV2,那么我们需要改动代码让它变成一个SomeServiceImplV2对象。

再看用了Spring之后

class SomeController{

    // 用了Spring之后
@Autowired
private SomeService service; public String doSomeThing(){
return service.getSomeThing();
}
}

这样做有什么效果呢?

1. 这个类只知道我依赖你哪一个接口,但是具体实现我就不管了。具体最终的实现类是哪一个,由第三方Spring负责注入。

2. 就算未来发生了变动,我们也不需要改动这部分代码。我们只需要告诉第三方Spring:这个接口的实现类变成V2版本了,你注入的时候注意一下。

这个重要的改变就是——控制反转(以前是我主动去控制依赖关系,现在是我被迫接受依赖关系,而这种关系的转变导致了代码的耦合度降低)

而实现控制反转的方式就是依赖注入——在运行期间,由IOC容器动态地将某种依赖关系注入到对象之中

所以

Spring是IOC理论的实践。通过把代码之间的依赖关系交给Spring来管理,解决了代码耦合的问题。

AOP

Spring另一个特性就是AOP(面向切面编程),又是一个晦涩难懂的名词。

先来看一个例子

引入依赖

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>

写个配置类

package com.demo.aop;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy; @Configuration
@ComponentScan("com.demo.aop")
@EnableAspectJAutoProxy
public class SimpleConfig {
}

写个业务接口

package com.demo.aop;

public interface SimpleService {
void fun();
}

写个业务实现

package com.demo.aop;

import org.springframework.stereotype.Service;

@Service
public class SimpleServiceImpl implements SimpleService { public void fun(){
System.out.println("业务方法...");
}
}

写个日志类

package com.demo.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component; /**
* 日志类就是一个切面
*/
@Aspect
@Component
public class LogAOP { /**
* 具体业务方法就是切入点
*/
@Pointcut("execution(* com.demo.aop.*.*(..))")
public void aspect(){} /**
* 通知(before/after/around)
* @param joinPoint
* @return
* @throws Throwable
*/
@Around("aspect()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println(">>>>>>>>业务方法之前");
long start = System.currentTimeMillis();
Object proceed = joinPoint.proceed();
long end = System.currentTimeMillis();
System.out.println(">>>>>>>>业务方法之后");
System.out.println(joinPoint + "|Time-Consuming:" + (end-start));
return proceed;
} /**
* 如果出现异常
* @param joinPoint
* @param e
*/
@AfterThrowing(pointcut = "aspect()", throwing = "e")
public void afterException(JoinPoint joinPoint, Exception e){
// TODO
}
}

最后写一个启动方法

package com.demo.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Main {
public static void main(String[] args) throws Exception {
ApplicationContext context = new AnnotationConfigApplicationContext(SimpleConfig.class);
SimpleService bean = context.getBean(SimpleService.class);
bean.fun();
} }

输出:

写这么多,只完成了一件事情——在业务方法前后做一些额外的工作。

那么AOP出现的原因呢?

1. 没有AOP,如果我们想要在一批接口方法执行的前后做一些额外的工作,那么每个方法我们都要写重复的逻辑代码,这可是个体力活。

2. 使用AOP,我们只需要写好额外工作的逻辑,然后配置一下,就可以在一批方法的前后执行我们写好的处理逻辑了。

3. 解决了代码重复的问题,实现了代码复用。

利用AOP可以做很多事情,比如:拦截器、日志、事务管理等等

下面是AOP相关概念

切面(Aspect):要增强的内容,比如上面例子中的日志类

连接点(JoinPoint):从哪里增强,比如上面例子中具体的业务方法就是连接点

切入点(PonitCut):从哪里增强,比如上面例子中具体的业务方法的集合就是切入点

通知(Advise):具体增强的逻辑,比如上面日志类中的方法(@Around标记)

切入点表达式(execution):

常见的比如:

IOC和AOP小结

IOC:对象之间的依赖关系交由容器处理,【降低组件的耦合度】。不用IOC的话,会出现编码依赖问题:程序要分层,层与层之间调用就会存在依赖。一般都是new一个接口的具体实现类,这是硬编码的方式,如果改了需求,还要重新编译class,这也体现不出面向接口编程的好处。最直观的表达就是,IOC让对象的创建不用去new了,而是由spring利用Java的反射机制,根据配置在运行时动态的去创建以及管理对象。

AOP:支持将一些通用任务,如安全、事务、日志、权限等进行集中式管理,减少重复代码,从而提供更好的【代码复用】。比如我要在一批方法前后做一些相同的事情,不用AOP的话每个方法前后都要写一堆同样的处理逻辑。

IOC让相互协作的组件保持松散的耦合,而AOP编程允许你把遍布于应用各层的功能分离出来形成可重用的功能组件。

Spring事务

数据库-事务特性(ACID)

⑴ 原子性(Atomicity)
一个事务内所有操作共同组成一个原子包,要么全部成功,要么全部失败。

⑵ 一致性(Consistency)
数据库事务的一致性就规定了事务提交前后,永远只可能存在事务提交前的状态和事务提交后的状态,从一个一致性的状态到另一个一致性状态,而不可能出现中间的过程态。

⑶ 隔离性(Isolation)
事务的隔离性,基于原子性和一致性,每个事务互不干扰。

⑷ 持久性(Durability)
持久性,当一个事物提交之后,数据库状态永远的发生了改变。

数据库-隔离级别

⑴ 读未提交
在这种隔离级别下,查询是不会加锁的,所以这种隔离级别的一致性是最差的,可能会产生“脏读”、“不可重复读”、“幻读”。

⑵ 读已提交
只能读到其它事务已经提交的内容。没有查询加锁,但是却能够避免脏读。可能会产生“不可重复读”、“幻读”。

⑶ 可重复读
可以防止“脏读”、“不可重复读”。可能会产生“幻读”。

⑷ 串行化
在该级别下,事务顺序执行,不仅避免了脏读,不可重复读,而且避免了幻读。由于加锁,导致大量的请求超时,因此性能会比较低下。

脏读:一个事务读到另一个事务未提交的数据
不可重复读:一个事务读到另一个事务已提交的更新的数据。【多次读取数据内容不一致】
幻读:一个事务读到另一个事务已提交的新插入的数据。【多次读取数据数量不一致】。

Spring事务传播(7种)

Propagation.REQUIRED:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是Spring默认的选择。
Propagation.SUPPORTS:支持当前事务,如果没有当前事务,就以非事务方法执行。
Propagation.MANDATORY:支持当前事务,如果没有当前事务,就抛出异常。
Propagation.REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
Propagation.NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
Propagation.NEVER:以非事务方式执行操作,如果当前事务存在则抛出异常。
Propagation.NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

具体使用也是非常简单

@Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED)
public void addXXX(UserRequest request) {
// 业务逻辑
}

Spring之IOC、AOP和事务的更多相关文章

  1. Spring学习之AOP与事务

      一.概述 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续, ...

  2. spring中使用aop配置事务

    spring的事务配置有5种方式,这里记录其中的一种:基于tx/aop声明式事务配置 在之前spring aop介绍和示例这篇所附代码的基础上进行测试 一.添加save方法 1.在testDao类里添 ...

  3. Spring(二)--IoC&AOP

    IOC 一.IOC概述: 一般指控制反转(inversion of Control),把创建对象的权利交给框架,Ioc容器控制对象,是框架的重要特征,并非是面向对象编程的专用术语.它包括依赖注入(DI ...

  4. Spring核心--IOC&AOP

    Ioc(控制反转) 所谓的控制反转就是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的.这样控制权就由应用转移到了外部容器,控制权的转移就是所谓反转. AOP(面向切面编程) ...

  5. spring的IOC和AOP

     spring的IOC和AOP 1.解释spring的ioc? 几种注入依赖的方式?spring的优点? IOC你就认为他是一个生产和管理bean的容器就行了,原来需要在调用类中new的东西,现在都是 ...

  6. spring的IOC和AOP详细讲解

    1.解释spring的ioc? 几种注入依赖的方式?spring的优点? IOC你就认为他是一个生产和管理bean的容器就行了,原来需要在调用类中new的东西,现在都是有这个IOC容器进行产生,同时, ...

  7. Spring整合JDBC以及AOP管理事务

    本节内容: Spring整合JDBC Spring中的AOP管理事务 一.Spring整合JDBC Spring框架永远是一个容器,Spring整合JDBC其实就是Spring提供了一个对象,这个对象 ...

  8. 04 Spring:01.Spring框架简介&&02.程序间耦合&&03.Spring的 IOC 和 DI&&08.面向切面编程 AOP&&10.Spring中事务控制

    spring共四天 第一天:spring框架的概述以及spring中基于XML的IOC配置 第二天:spring中基于注解的IOC和ioc的案例 第三天:spring中的aop和基于XML以及注解的A ...

  9. Spring(IOC、AOP和事务)

    目录 Spring介绍 Spring IOC 传统代码对象管理的弊端 实现过程 bean标签属性介绍 对象创建方式 工厂bean bean的作用域 SpringBean的生命周期*** 依赖注入 注解 ...

随机推荐

  1. oracle常见的函数

    1.字符函数 -- initcap函数只针对英文 select * from tb_user where user_name = initcap('张三'); -- ltrim 左剪切 select ...

  2. Educational Codeforces Round 81 (Rated for Div. 2) - D. Same GCDs(数学)

    题目链接:Same GCDs 题意:给你两个数$a$,$m(1 \leq a < m \leq 10^{10})$,求有多少个$x$满足:$0 \leq x < m$且$gcd(a,m)= ...

  3. mysql中utf8字符集的设置及character_set_database属性修改

    mariadb配置文件修改字符集: [mysqld] atadir=/usr/local/mysql/datasocket=/tmp/mysql.sock # Disabling symbolic-l ...

  4. 「SDOI2009」虔诚的墓主人

    传送门 Luogu 解题思路 离散化没什么好说 有一种暴力的想法就是枚举每一个坟墓,用一些数据结构维护一下这个店向左,向右,向上,向下的常青树的个数,然后用组合数统计方案. 但是网格图边长就有 \(1 ...

  5. Python - 静态方法@staticmethod和类方法classmethod

    传送门 https://github.com/jackfrued/Python-100-Days/blob/master/Day01-15/Day09/%E9%9D%A2%E5%90%91%E5%AF ...

  6. Update(stage3):第1节 redis组件:10、redis集群

    10.redis集群 1.redis集群的介绍 Redis 集群是一个提供在多个Redis节点之间共享数据的程序集. Redis 集群并不支持同时处理多个键的 Redis 命令,因为这需要在多个节点间 ...

  7. iOS 增强程序健壮性 - - 使用 NullSafe 对 <null> 处理

    在项目开发中,和服务端交互数据时,若服务端数据为空时,会出现 <null>,客户端解析时会 Crash,为了增强程序的健壮性,减少 Crash 的发生,可以使用 NullSafe 这个类别 ...

  8. MavenProfile简介

    在我们平常的java开发中,会经常使用到很多配制文件(xxx.properties,xxx.xml),而当我们在本地开发(dev),测试环境测试(test),线上生产使用(product)时,需要不停 ...

  9. how to analyze jmeter results

    https://octoperf.com/blog/2017/10/19/how-to-analyze-jmeter-results/

  10. OS(操作系统)结构

    1.整体式: 模块设计(独立的) 调用自由 用全局变量来通信 缺点:信息不安全,维护更新比较难 2.层次结构(典型的如TCP/IP协议): 所有的模块排成若干层,相邻的互相依赖调用 按调用次序来安排 ...