ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] ## 一、谈谈自己对于 Spring IoC 和 AOP 的理解 ### IoC IoC(Inverse of Control:控制反转)是一种**设计思想**,就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。IoC 在其他语言中也有应用,并非 Spring 特有。**IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个Map(key,value),Map 中存放的是各种对象。** **IoC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。** ### AOP AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,**却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来**,便于**减少系统的重复代码**,**降低模块间的耦合度**,并**有利于未来的可拓展性和可维护性**。 #### 动态代理 **Spring AOP就是基于动态代理的**,如果要代理的对象,实现了某个接口,那么Spring AOP会使用**JDK Proxy**,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候Spring AOP会使用**Cglib**,这时候Spring AOP会使用**Cglib**生成一个`被代理对象的子类`来作为代理,如下图所示: ![SpringAOPProcess](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/SpringAOPProcess.jpg) 当然你也可以使用 `AspectJ `,Spring AOP 已经集成了AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。 ### Spring AOP 和 AspectJ AOP 有什么区别? | 比较| SpringAOP | AspectJ | | --- | --- | --- | |**增强类型**| 运行时增强 | 编译时增强 | | **易用程度**| 相对简单 | 相对复杂 | | **性能选型** | 切面较少用| 切面复杂用| |**实现原理**| 通过拦截器+反射;实质上是通过反射将被代理类的加载器和接口与代理对象关联起来。| 基于ASM实现,性能比较高| 1. Spring AOP 属于**运行时增强**,而 AspectJ 是**编译时增强**。Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。 2. Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单, 3. 如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择 AspectJ ,它比Spring AOP 快很多。 #### 使用区别 JDK 动态代理与 CGLIB 动态代理都是将真实对象`隐藏`在代理对象的后面,以达到 `代理` 的效果。与 JDK 动态代理所不同的是 CGLIB 动态代理使用 Enhancer 来创建代理对象,而 JDK 动态代理使用的是 Proxy.newProxyInstance 来创建代理对象;还有一点是 CGLIB 可以代理大部分类,而 JDK 动态代理只能代理实现了接口的类。 ### 动态代理的实现原理 JDK:实质上是通过反射将被代理类的加载器和接口与代理对象关联起来。 案例:jdk动态代理的使用方法。 ``` /** * 基于jdk反射包下Proxy进行service的代理 * 结果:报错,JDK的动态代理需要是一个接口;cglib才能动态代理类对象 */ @Test public void test_proxy_class() { UserCertificateService userCertificateService = (UserCertificateService) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader() , new Class[]{UserCertificateService.class}, ((proxy, method, args) -> "你被代理了")); UserCertificate userCertificate = userCertificateService.selectById(100); System.out.println(JSONObject.toJSONString(userCertificate)); } ``` ``` java.lang.IllegalArgumentException: com.keyou.evm.lpm.service.UserCertificateService is not an interface ```