- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
本文摘录自笔者开源的 Java 学习&面试指南(Github 收获146k star):JavaGuide .
这篇文章会从下面从以下几个问题展开对 IoC & AOP 的解释 。
首先声明:IoC & AOP 不是 Spring 提出来的,它们在 Spring 之前其实已经存在了,只不过当时更加偏向于理论。Spring 在技术层次将这两个思想进行了很好的实现.
IoC (Inversion of Control )即控制反转/反转控制。它是一种思想不是一个技术实现。描述的是:Java 开发领域对象的创建以及管理的问题.
例如:现有类 A 依赖于类 B 。
从以上两种开发方式的对比来看:我们 “丧失了一个权力” (创建、管理对象的权力),从而也得到了一个好处(不用再考虑对象的创建、管理等一系列的事情) 。
为什么叫控制反转?
IoC 的思想就是两方之间不互相依赖,由第三方容器来管理相关资源。这样有什么好处呢?
例如:现有一个针对 User 的操作,利用 Service 和 Dao 两层结构进行开发 。
在没有使用 IoC 思想的情况下,Service 层想要使用 Dao 层的具体实现的话,需要通过 new 关键字在UserServiceImpl 中手动 new 出 IUserDao 的具体实现类 UserDaoImpl(不能直接 new 接口类).
很完美,这种方式也是可以实现的,但是我们想象一下如下场景:
开发过程中突然接到一个新的需求,针对IUserDao 接口开发出另一个具体实现类。因为 Server 层依赖了IUserDao的具体实现,所以我们需要修改UserServiceImpl中 new 的对象。如果只有一个类引用了IUserDao的具体实现,可能觉得还好,修改起来也不是很费力气,但是如果有许许多多的地方都引用了IUserDao的具体实现的话,一旦需要更换IUserDao 的实现方式,那修改起来将会非常的头疼.
使用 IoC 的思想,我们将对象的控制权(创建、管理)交由 IoC 容器去管理,我们在使用的时候直接向 IoC 容器 “要” 就可以了 。
IoC(Inverse of Control:控制反转)是一种设计思想或者说是某种模式。这个设计思想就是 将原本在程序中手动创建对象的控制权交给第三方比如 IoC 容器。 对于我们常用的 Spring 框架来说, IoC 容器实际上就是个 Map(key,value),Map 中存放的是各种对象。不过,IoC 在其他语言中也有应用,并非 Spring 特有.
IoC 最常见以及最合理的实现方式叫做依赖注入(Dependency Injection,简称 DI).
老马(Martin Fowler)在一篇文章中提到将 IoC 改名为 DI,原文如下,原文地址:https://martinfowler.com/articles/injection.html .
老马的大概意思是 IoC 太普遍并且不表意,很多人会因此而迷惑,所以,使用 DI 来精确指名这个模式比较好.
这里不会涉及太多专业的术语,核心目的是将 AOP 的思想说清楚.
AOP(Aspect Oriented Programming)即面向切面编程,AOP 是 OOP(面向对象编程)的一种延续,二者互补,并不对立.
AOP 的目的是将横切关注点(如日志记录、事务管理、权限控制、接口限流、接口幂等等)从核心业务逻辑中分离出来,通过动态代理、字节码操作等技术,实现代码的复用和解耦,提高代码的可维护性和可扩展性。OOP 的目的是将业务逻辑按照对象的属性和行为进行封装,通过类、对象、继承、多态等概念,实现代码的模块化和层次化(也能实现代码的复用),提高代码的可读性和可维护性.
AOP 之所以叫面向切面编程,是因为它的核心思想就是将横切关注点从核心业务逻辑中分离出来,形成一个个的切面(Aspect).
这里顺带总结一下 AOP 关键术语(不理解也没关系,可以继续往下看):
execution(* com.xyz.service..*(..))
匹配 com.xyz.service
包及其子包下的类或接口。OOP 不能很好地处理一些分散在多个类或对象中的公共行为(如日志记录、事务管理、权限控制、接口限流、接口幂等等),这些行为通常被称为 横切关注点(cross-cutting concerns) 。如果我们在每个类或对象中都重复实现这些行为,那么会导致代码的冗余、复杂和难以维护.
AOP 可以将横切关注点(如日志记录、事务管理、权限控制、接口限流、接口幂等等)从 核心业务逻辑(core concerns,核心关注点) 中分离出来,实现关注点的分离.
以日志记录为例进行介绍,假如我们需要对某些方法进行统一格式的日志记录,没有使用 AOP 技术之前,我们需要挨个写日志记录的逻辑代码,全是重复的的逻辑.
public CommonResponse<Object> method1() {
// 业务逻辑
xxService.method1();
// 省略具体的业务处理逻辑
// 日志记录
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 省略记录日志的具体逻辑 如:获取各种信息,写入数据库等操作...
return CommonResponse.success();
}
public CommonResponse<Object> method2() {
// 业务逻辑
xxService.method2();
// 省略具体的业务处理逻辑
// 日志记录
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 省略记录日志的具体逻辑 如:获取各种信息,写入数据库等操作...
return CommonResponse.success();
}
// ...
使用 AOP 技术之后,我们可以将日志记录的逻辑封装成一个切面,然后通过切入点和通知来指定在哪些方法需要执行日志记录的操作.
// 日志注解
@Target({ElementType.PARAMETER,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
/**
* 描述
*/
String description() default "";
/**
* 方法类型 INSERT DELETE UPDATE OTHER
*/
MethodType methodType() default MethodType.OTHER;
}
// 日志切面
@Component
@Aspect
public class LogAspect {
// 切入点,所有被 Log 注解标注的方法
@Pointcut("@annotation(cn.javaguide.annotation.Log)")
public void webLog() {
}
/**
* 环绕通知
*/
@Around("webLog()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
// 省略具体的处理逻辑
}
// 省略其他代码
}
这样的话,我们一行注解即可实现日志记录:
@Log(description = "method1",methodType = MethodType.INSERT)
public CommonResponse<Object> method1() {
// 业务逻辑
xxService.method1();
// 省略具体的业务处理逻辑
return CommonResponse.success();
}
@Transactional
注解可以让 Spring 为我们进行事务管理比如回滚异常操作,免去了重复的事务管理逻辑。@Transactional
注解就是基于 AOP 实现的。@PreAuthorize
注解一行代码即可自定义权限校验。AOP 的常见实现方式有动态代理、字节码操作等方式.
Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用 JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib 生成一个被代理对象的子类来作为代理,如下图所示:
当然你也可以使用 AspectJ !Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了.
Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation).
Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单, 。
如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择 AspectJ ,它比 Spring AOP 快很多.
最后此篇关于面试官:谈谈你对IoC和AOP的理解!的文章就讲到这里了,如果你想了解更多关于面试官:谈谈你对IoC和AOP的理解!的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
php7发布已有半月,最近有时间了解一下php7的新特性,当然,这个版本最大的特点是性能的提升。在下并非高手,欢迎大家指出错误,同时期待共同交流。 PHP语言一个非常重要的特点就是“弱类型”,它让
前言 最近业务开发中,有遇到我们的项目 app 定位被篡改的情况,在 android 端表现的尤为明显。为了防止这种黑产使用虚拟定位薅羊毛,iOS 也不得不进行虚拟定位的规避。 在做技术调研
2014 年发布的 Kubernetes 在今天俨然已成为容器编排领域的事实标准,相信谈到 Kubernetes 的开发者都会一再复述上述现象。如下图所示,今天的大多数个人或者团队都会选择 Ku
不用程序员操心的堆 —托管堆 程序在计算机上跑着,就难免会占用内存资源来存储在程序运行过程中的数据,我们按照内存资源的存取方式将内存划分为堆内存和栈内存。 栈内存,通常使用的场景是:对
前言 在上一讲 谈谈 Nginx 那点事【一】 中,介绍了Nginx的安装及基本结构,今天将工作中Nginx的一些配置,及常用的场景做一些总结。 这一讲总结的内容主要是关于Nginx服务配置、静态资源
1. this是指当前对象自己。 当在一个类中要明确指出使用对象自己的的变量或函数时就应该加上this引用。如下面这个例子中: &nb
前言 ESLint 在项目中已经是大家见惯不惯的存在,你可能很厌烦动不动跳出来的 ESLint 报错,也可能很享受经过统一校验的工工整整的代码,无论如何,我的意见是,在稍微正式点的项目中都要有
背景 从写 Flutter 第一行程序开始我们就知道在 Dart 的 main 方法中通过调用 runApp 方法把自己编写的 Widget 传递进去,只有这样编译运行后才能得到预期效果。你有
我是一名优秀的程序员,十分优秀!