Spring AOP和IOC

概述

Spring框架中的AOP(Aspect-Oriented Programming)和IOC(Inversion of Control)是两个核心概念,它们在Spring应用中起着重要作用。

  1. IOC(Inversion of Control):
    IOC是一种设计原则,它反转了传统的程序设计中对象控制的方式。在传统的程序设计中,通常由程序自身控制对象的创建和管理,而在IOC容器中,控制权被反转,即由容器来创建和管理对象。在Spring框架中,IOC容器负责管理应用中的对象,它通过依赖注入(Dependency Injection)的方式来将对象之间的依赖关系注入到对象中。这样做的好处是降低了组件之间的耦合度,使得代码更加灵活、可维护和可测试。
  2. AOP(Aspect-Oriented Programming):
    AOP是一种编程范式,它通过在程序中定义切面(Aspect)来实现对横切关注点(Cross-cutting Concerns)的模块化。横切关注点是指跨越应用程序多个模块的功能,如日志记录、事务管理、安全性等。在传统的面向对象编程中,这些关注点往往会与业务逻辑混在一起,导致代码的复杂性和重复性增加。而通过AOP,可以将这些横切关注点与业务逻辑分离开来,以切面的方式进行统一管理和维护。Spring框架提供了强大的AOP支持,通过使用AOP可以很容易地实现诸如日志记录、性能监控、事务管理等功能。
    综上所述,IOC和AOP是Spring框架中两个重要的概念,它们分别通过控制反转和面向切面编程的方式,提高了应用程序的灵活性、可维护性和可扩展性。

AOP

AOP面向切面编程,将代码中重复的部分抽取出来,使用动态代理技术,在不修改源码的基础上对方法进行增强。
如果目标对象实现了接口,默认采用JDK动态代理,也可以强制使用CGLib,如果目标对象没有实现接口,采用CGLib的方式。
AOP 核心概念
1、切面(aspect):类是对物体特征的抽象,切面就是对横切关注点的抽象
2、横切关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点。
3、连接点(joinpoint):被拦截到的点,因为 Spring 只支持方法类型的连接点,所以在 Spring
中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器。
4、切入点(pointcut):对连接点进行拦截的定义
5、通知(advice):所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、
异常、最终、环绕通知五类。
6、目标对象:代理的目标对象
7、织入(weave):将切面应用到目标对象并导致代理对象创建的过程
8、引入(introduction):在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法
或字段。

Spring的AOP的底层实现原理

Spring AOP 中的动态代理主要有两种方式,JDK 动态代理和 CGLIB 动态代理。JDK 动态代
理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK 动态代理的
核心是 InvocationHandler 接口和 Proxy 类。如果目标类没有实现接口,那么 Spring AOP 会选择使用 CGLIB 来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为 final,那么它是无法使用 CGLIB 做动态代理的。
动态代理(cglib 与 JDK)
JDK 动态代理类和委托类需要都实现同一个接口。也就是说只有实现了某个接口的类可以使用 Java 动态代理机制。但是,事实上使用中并不是遇到的所有类都会给你实现一个接口。因此,对于没有实现接口的类,就不能使用该机制。而 CGLIB 则可以实现对类的动态代理。
底层基于动态代理模式实现,如果我们的目标类有实现接口的情况下则采用JDK动态代理,如果我们的目标类没有实现接口的情况下则采用cglib动态代理

JDK动态代理跟CGLib动态代理的区别 (ms高频)

Spring 提供了两种方式来生成代理对象: JDKProxy 和 Cglib,具体使用哪种方式生成由AopProxyFactory 根据 AdvisedSupport 对象的配置来决定。默认的策略是如果目标类是接口,则使用 JDK 动态代理技术,
1、如果目标对象实现了接口,默认情况下会采用 JDK 的动态代理实现 AOP
2、如果目标对象实现了接口,可以强制使用 CGLIB 实现 AOP
3、如果目标对象没有实现了接口,必须采用 CGLIB 库,spring 会自动在 JDK 动态代理和 CGLIB 之间转换

  1. JDK动态代理通过反射去实现被代理对象的所有接口,所以JDK只能代理实现了接口的对象,CGLlib对代理类所有方法重写,所以private的方法都不能被代理,不是所有的方法都能被代理
  2. JDK动态代理跟CGLib代理都是在运行期生成新的字节码,但是CGLib实现更为复杂,用的是ASM框架,生成代理类的效率比JDK低
  3. JDK动态代理是通过反射机制去查询所有被代理对象的接口,CGLib代理是通过FastClass机制直接调用方法,所有执行效率,CGLib比JDK代理要高
    4.spring用的是哪个代理模式 bean有实现接口的时候用jdk,没有实现的话模式cglib,也可以强制用cglib
    1JDK Proxy是实现目标对象的接口,而GGLib是继承目标对象
    JDK Proxy和CGLib都是在运行期生成字节码。
    JJDK Proxy是通过反射调用目标对象的方法,而CGLib是采用FastClass机制来调用

动态代理

aop是ioc的一个扩展功能,先有的ioc再有的aop,aop只是在ioc的整个流程中新增的一个扩展点而已:BeanPostPOrcessor
总:aop的概念,应用场景,动态代理
分:bean的创建过程中有一个步骤可以对bean进行扩展实现,aop本身就是一个扩展功能,所以在BeanPostProcess的后置处理方法中来进行实现
1.代理对象的创建过程(advice,切面,切点)
2.通过jdk或者cglib的方式来生成代理对象
3.在执行方法调用的时候,会调用到生成的字节码文件中,会直接找到DynamicAdvisoredInterceptor类中的intercept方法,从此方法开始执行
4.根据之前定义好的通知来生成拦截器链
5.从拦截器链中一次获取每一个通知开始进行执行,在执行过程中,为了方便找到下一个通知是哪个,会有一个InvocationInterceptor的对象,找的时候是从-1的位置一次开始查找并且执行的

Spring Aop有哪些应用场景

Spring Aop有哪些作用
可以解决我们代码重复性问题,对我们代码实现额外功能增强。
前置 后置 环绕 异常 等通知
主要应用场景:日志、权限、事务
常用的场景包括权限认证、自动缓存、错误处理、日志、调试和事务等
日志的采集、权限控制 aop 拦截器、Mybatis mapper、Spring的事务、全局捕获异常、Rpc远程调用接口 (传递就是接口)、代理数据源、自定义注解

Spring的AOP在什么场景下会失效

在以下场景下,Spring 的 AOP 可能会失效:

  1. 内部方法调用:AOP 是通过代理对象实现的,当目标方法在同一个类中的其他方法中被调用时,AOP 无法拦截这些内部方法调用。因为代理对象只能拦截从外部调用的方法。
  2. 非 public 方法调用:AOP 默认只能拦截公共的(public)方法,对于私有的(private)、受保护的(protected)以及默认访问级别的方法,AOP 无法进行拦截。
  3. 静态方法调用:AOP 是基于动态代理实现的,而静态方法是在编译时就确定调用的,不会通过代理对象进行调用,因此 AOP 无法拦截静态方法。
  4. 同一类中的方法互相调用:当同一个类中的方法互相调用时,AOP 也会失效。因为 Spring AOP 是基于代理对象实现的,代理对象只能拦截外部对目标方法的调用,而无法拦截目标方法内部的方法调用。
  5. 直接通过实例调用方法:如果代码直接通过实例对象调用方法,而不是通过 Spring 容器获取的代理对象调用方法,那么 AOP 也无法生效。
    需要注意的是,上述情况对于 Spring 的默认 AOP 实现来说是存在的,但可以通过使用 AspectJ 来解决这些限制。AspectJ 是一个功能更强大的 AOP 框架,它可以在编译期、类加载期或者运行期进行 AOP 操作,可以绕过上述的限制,实现对更多场景的拦截和增强。

IoC

控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
IOC的全称是Inversion Of Control,也就是控制反转,它的核心思想是把对象的管理权限
交给容器。应用程序如果需要使用到某个对象实例,直接从IOC容器中去获取就行,这样设计的好处
是降低了程序里面对象与对象之间的耦合性。使得程序的整个体系结构变得更加灵活。
Spring里面很多方式去定义Bean, 比如XML里面的标签、@Service、
@Component、@Repository、@Configuration配置类中的@Bean注解等等。
Spring在启动的时候,会去解析这些Bean然后保存到IOC容器里面。

spring IOC的底层实现

底层实现:工作原理,过程,数据结构,流程,设计模式,设计思想
反射,工厂,涉及模式,关键的几个方法
createBeanFactory,getBean,doGetBean,createBean,doCreateBean,createBeanInstance,populateBean,
加do的方法都是实际干活的方法,不加do的都是在前面套一层
1.先通过createBeanFactory创建出一个Bean工厂(DefaultListableBeanFactory)
2.开始循环创建对象,因为容器中的bean默认都是单例的,所以优先通过getBean,doGetBean从容器中查找
3.找不到的话,通过createBean,doCreateBean方法,以反射的方式创建对象,一般情况下使用的是无参的构造方法(getDeclaredConstructor,newInstance)
4.进行对象的属性填充populateBean
5.进行其他的初始化操作(initalizingBean)
底层实现
1.spring通过解析配置文件或者注解方式加载到DefaultListableBeanFactory工厂
2.DefaultListableBeanFactory向IoC容器注册解析后的BeanDefinition
3.IOC容器本质上就是一个beanDefinitionMap, 注册即将BeanDefinition put到map中,已经注册到IoC容器中,被容器管理起来
4.遍历map,实例化(反射),容器可以进行依赖注入DI填充属性,开始初始化

Spring IoC的实现过程和IOC 工作流程

1.spring通过解析配置文件或者注解方式加载到DefaultListableBeanFactory工厂
2.DefaultListableBeanFactory向IoC容器注册解析后的BeanDefinition
3.IOC容器本质上就是一个beanDefinitionMap, 注册即将BeanDefinition put到map中,已经注册到IoC容器中,被容器管理起来
4.遍历map,实例化(反射),容器可以进行依赖注入DI填充属性,开始初始化
IOC 工作流程
Spring IOC的工作流程大致可以分为三个阶段
第一个阶段,就是IOC容器的初始化
这个阶段主要是根据程序中定义的XML或者注解等Bean的声明方式
通过解析和加载后生成BeanDefinition,然后把BeanDefinition注册到IOC容器。
通过注解或者xml声明的bean都会解析得到一个BeanDefinition实体,实体中包含这个bean中定义的基本属性。
最后把这个BeanDefinition保存到一个Map集合里面,从而完成了IOC的初始化。
IoC容器的作用就是对这些注册的Bean的定义信息进行处理和维护,它IoC容器控制反转的核心。
第二个阶段,完成Bean初始化及依赖注入
然后进入到第二个阶段,这个阶段会做两个事情,通过反射针对没有设置lazy-init属性的单例bean进行初始化。
完成Bean的依赖注入。
第三个阶段,Bean的使用
通常我们会通过@Autowired或者BeanFactory.getBean()从IOC容器中获取指定的bean实例。
另外,针对设置layy-init属性以及非单例bean的实例化,是在每次获取bean对象的时候,
调用bean的初始化方法来完成实例化的,并且Spring IOC容器不会去管理这些Bean。

Spring 的依赖注入

平常的 java 开发中,程序员在某个类中需要依赖其它类的方法,则通常是 new 一个依赖类再调用类实例的方法,这种开发存在的问题是 new 的类实例不好统一管理,spring 提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过 spring 容器帮我们 new 指定实例并且将实例注入到需要该对象的类中。依赖注入的另一种说法是“控制反转”,通俗的理解是:平常我们 new 一个实例,这个实例的控制权是我们程序员,而控制反转是指 new 实例工作不由我们程序员来做而是交给 spring 容器来做。
1. 接口注入2. Setter方法注入3. 构造方法注入

  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
当谈到Spring框架的面试题时,Spring AOPIOC是两个常见的话题。下面是一些可能的面试问题和答案: 1. 什么是Spring AOPSpring AOP是一种基于面向切面编程(AOP)的技术,它允许开发人员在应用程序中定义横切关注点,并将它们与应用程序的业务逻辑相分离。通过将这些横切关注点(例如日志记录、事务管理等)从核心业务逻辑中提取出来,可以实现更好的模块化和可维护性。 2. Spring AOP的工作原理是什么? Spring AOP通过使用代理模式在运行时为目标对象动态地创建代理对象来实现横切关注点的功能。当调用目标方法时,代理对象会在执行前、执行后或异常发生时插入相关的横切逻辑。 3. Spring IOC是什么意思? Spring IOC(控制反转)是一种设计模式,它将对象的创建和依赖关系的管理从应用程序代码中解耦出来,交由框架来完成。通过IOC容器,可以通过配置文件或注解方式来定义对象之间的依赖关系,Spring容器负责创建、装配和管理这些对象。 4. Spring IOC的优势是什么? 使用Spring IOC可以实现松耦合的设计,从而提高代码的可维护性和可测试性。它还提供了更好的可扩展性,通过配置文件或注解方式,可以方便地修改对象的依赖关系而无需修改代码。此外,Spring IOC还可以通过依赖注入的方式简化对象之间的协作。 5. Spring AOPIOC之间有什么关系? Spring AOPSpring框架的一个重要模块,它通过IOC容器来管理和应用横切关注点。在Spring中,AOP是建立在IOC的基础上的,通过IOC容器的支持,可以方便地在应用程序中应用AOP功能。 请注意,这些问题只是众多可能的面试问题中的一部分,面试官可能会根据他们的需求提出更具体的问题。为了取得良好的面试成绩,建议您深入了解Spring AOPIOC的概念、工作原理以及在实际项目中的应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

思静语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值