Spring系统之IOC与AOP

前言

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。


IOC

1.IOC的概念

控制反转(IoC=Inversion of Control)IoC,用白话来讲,就是由容器控制程序之间的(依赖)关系,而非传统实现中,由程序代码直接操控。这也就是所谓"控制反转"的概念所在:(依赖)控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。

IoC还有一个另外的名字:"依赖注入 (DI=Dependency Injection)" ,即由容器动态的将某种依赖关系注入到组件之中

案例:实现Spring的IoC

IOC/DI
将以前由程序员实例化对象/赋值的工作交给了spring处理

2.IOC的运用

Spring IoC容器常用的实现是ApplicationContext,它是一个具有丰富功能的IoC容器。通过在配置文件中定义Bean的信息,或使用注解方式进行配置,应用程序可以借助ApplicationContext来获取所需的Bean实例,并利用容器提供的功能,如AOP(面向切面编程)、事务管理等。

3.IOC的特点

Spring IoC通过将对象的创建、组装和管理任务交给容器来完成,实现了对象之间的解耦和灵活性。它简化了应用程序的开发和维护,提高了代码的可复用性和可测试性。同时,Spring IoC还提供了丰富的功能和扩展点,使得开发者可以更加方便地进行企业级应用程序的开发。

4.IOC的底层逻辑

IoC 底层通过工厂模式、Java 的反射机制、XML 解析等技术,将代码的耦合度降低到最低限度,其主要步骤如下。

  1. 在配置文件(例如 Bean.xml)中,对各个对象以及它们之间的依赖关系进行配置;
  2. 我们可以把 IoC 容器当做一个工厂,这个工厂的产品就是 Spring Bean;
  3. 容器启动时会加载并解析这些配置文件,得到对象的基本信息以及它们之间的依赖关系;
  1. IoC 利用 Java 的反射机制,根据类名生成相应的对象(即 Spring Bean),并根据依赖关系将这个对象注入到依赖它的对象中。

5.IOC的注入方式

a.set注入 property name value ref

基本数据注入

String

自定义类型注入(开放中常用)

b.构造注入 construct-arg

c.自动装配

byName 根据当前Bean对象中属性名去spring上下文

byType 根据接口自动在spring的上下文去找实现类

AOP

1.AOP的概念

Spring AOP(Aspect-oriented Programming,面向切面编程)是Spring框架提供的一个重要特性,用于实现横切关注点的模块化和可重用性。它通过在不修改原有业务逻辑代码的情况下,将横切关注点与核心业务逻辑进行解耦,并通过切面(Aspect)来定义和管理这些关注点。

在传统的面向对象编程中,业务逻辑代码通常分散在各个对象中,而横切关注点(如日志记录、事务管理、安全控制等)则相互交织其中,导致代码的重复和难以维护。而Spring AOP则将横切关注点作为一个独立的模块,称为切面(Aspect),并通过一种称为切入点(Pointcut)的机制来选择在哪些连接点(Joinpoint)上应用切面。
AOP------ 即面向切面编程

2.AOP的核心

Spring AOP的核心概念包括以下几个:

  1. 目标(Target):被通知(被代理)的对象

  2. 连接点(Joinpoint):连接点是程序执行过程中可以插入切面的点。例如方法的调用、方法的执行、字段的访问等。

  3. 通知(Advice):通知定义了切面在连接点上执行的行为。包括前置通知(Before)、后置通知(After)、返回通知(After-returning)、异常通知(After-throwing)和环绕通知(Around)。

  4. 代理(Proxy):将通知应用到目标对象后创建的对象(代理=目标+通知),

  5. 切入点(Pointcut):切入点是通过表达式或注解来选择在哪些连接点上应用切面。连接点可以是方法的执行、方法的调用、字段的访问等。

  6. 适配器(Advisor):适配器=通知(Advice)+切入点(Pointcut)

  7. 切面(Aspect):切面是横切关注点的模块化和可重用单元。它由切入点、通知和其他配置元素组成。切面定义了应该在哪些连接点上执行特定的行为。

Spring AOP可以与Spring IoC容器无缝集成,通过配置文件或注解方式将切面定义为Bean,并由容器负责管理和应用。Spring AOP的实现基于动态代理技术,可以使用JDK动态代理或CGLIB字节码生成库来创建代理对象。

3.AOP的代理

工具类org.springframework.aop.framework.ProxyFactoryBean用于创建代理对象,并且在一般情况下需要注入以下三个属性:

  1. proxyInterfaces:代理应该实现的接口列表(List)。这个属性指定了代理对象应该实现的接口列表,通过实现这些接口,代理对象可以对外提供与目标对象相同的接口方法。

  2. interceptorNames:需要应用到目标对象上的通知Bean的名字(List)。这个属性指定了应该应用到目标对象上的通知Bean的名字列表。通知Bean是实现切面逻辑的对象,它定义了在目标对象的特定连接点上执行的操作。

  3. target:目标对象(Object)。这个属性指定了被代理的目标对象,即需要被代理的实际业务对象。

通过设置以上三个属性,ProxyFactoryBean可以根据配置创建一个代理对象,该代理对象可以拥有与目标对象相同的接口,并在方法调用前后应用通知逻辑。

java 复制代码
<bean id="targetObject" class="com.example.TargetObject" />

<bean id="adviceBean" class="com.example.AdviceBean" />

<bean id="proxyFactory" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="proxyInterfaces">
        <list>
            <value>com.example.TargetInterface</value>
        </list>
    </property>
    <property name="interceptorNames">
        <list>
            <value>adviceBean</value>
        </list>
    </property>
    <property name="target" ref="targetObject" />
</bean>

ProxyFactoryBean创建了一个代理对象,该代理对象实现了com.example.TargetInterface接口,并应用了名为adviceBean的通知Bean。被代理的目标对象是targetObject。

通过配置ProxyFactoryBean,我们可以将切面逻辑(adviceBean)与目标对象(targetObject)进行解耦,并最终得到一个代理对象,该代理对象可以在目标对象的方法调用前后执行通知逻辑。

ProxyFactoryBean提供了一种简单而灵活的方式来实现AOP和动态代理,可以帮助我们在应用程序中实现横切关注点的分离,并增加代码的可维护性和重用性。

4.AOP的通知类型

前置通知:在连接点之前执行的通知()

实现org.springframework.aop.MethodBeforeAdvice接口

买书、评论前加系统日志

后置通知:在连接点正常完成后执行的通知

实现org.springframework.aop.AfterReturningAdvice接口

买书返利(存在bug)

环绕通知:包围一个连接点的通知,最大特点是可以修改返回值,由于它在方法前后都加入了自己的逻辑代码,因此功能异常强大。

org.aopalliance.intercept.MethodInterceptor

类似拦截器,会包括切入点,目标类前后都会执行代码。

异常通知:这个通知会在方法抛出异常退出时执行

org.springframework.aop.ThrowsAdvice

出现异常执行系统提示,然后进行处理。价格异常为例

过滤通知(适配器):适配器=通知(Advice)+切入点(Pointcut)

org.springframework.aop.support.RegexpMethodPointcutAdvisor

处理买书返利的bug

面试题

1**、SpringIOCAOP机制?**

我们是在使用 Spring 框架的过程中,其实就是为了使用 IOC ,依赖注入,和 AOP ,面向切面编程,这两
个是 Spring 的灵魂。 主要用到的设计模式有工厂模式和代理模式。
IOC 就是典型的工厂模式,通过 sessionfactory 去注入实例。
AOP 就是典型的代理模式的体现。
代理模式是常用的 java 设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类
预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在
关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通
过调用委托类的对象的相关方法,来提供特定的服务。
spring IoC 容器是 spring 的核心, spring AOP spring 框架的重要组成部分。
在传统的程序设计中,当调用者需要被调用者的协助时,通常由调用者来创建被调用者的实例。但在
spring 里创建被调用者的工作不再由调用者来完成,因此控制反转( IoC );创建被调用者实例的工作通
常由 spring 容器来完成,然后注入调用者,因此也被称为依赖注入( DI ),依赖注入和控制反转是同一
个概念。
面向方面编程( AOP) 是以另一个角度来考虑程序结构,通过分析程序结构的关注点来完善面向对象编程
( OOP )。 OOP 将应用程序分解成各个层次的对象,而 AOP 将程序分解成多个切面。 spring AOP 只实
现了方法级别的连接点,在 J2EE 应用中, AOP 拦截到方法级别的操作就已经足够。在 spring 中,未来使
IoC 方便地使用健壮、灵活的企业服务,需要利用 spring AOP 实现为 IoC 和企业服务之间建立联系。
IOC: 控制反转也叫依赖注入。利用了工厂模式
将对象交给容器管理,你只需要在 spring 配置文件总配置相应的 bean ,以及设置相关的属性,让
spring 容器来生成类的实例对象以及管理对象。在 spring 容器启动的时候, spring 会把你在配置文件
中配置的 bean 都初始化好,然后在你需要调用的时候,就把它已经初始化好的那些 bean 分配给你需要
调用这些 bean 的类(假设这个类名是 A ),分配的方法就是调用 A setter 方法来注入,而不需要你在
A 里面 new 这些 bean 了。
注意:面试的时候,如果有条件,画图,这样更加显得你懂了 .
spring ioc 初始化流程
AOP: 面向切面编程。( Aspect-Oriented Programming
AOP 可以说是对 OOP 的补充和完善。 OOP 引入封装、继承和多态性等概念来建立一种对象层次结构,
用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候, OOP 则显得无能为力。
也就是说, OOP 允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代
码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。在 OOP 设计中,它
导致了大量代码的重复,而不利于各个模块的重用。
将程序中的交叉业务逻辑(比如安全,日志,事务等),封装成一个切面,然后注入到目标对象(具体
业务逻辑)中去。
实现 AOP 的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装
饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建 " 方面 " ,从而使得编
译器可以在编译期间织入有关 " 方面 " 的代码 .
简单点解释,比方说你想在你的 biz 层所有类中都加上一个打印 ' 你好 ' 的功能 , 这时就可以用 aop 思想来做 .
你先写个类写个类方法,方法经实现打印 ' 你好 ', 然后 Ioc 这个类 ref = "biz.*" 让每个类都注入即可实现。

2**、依赖注入的方式有几种,各是什么****?**

一、构造器注入
将被依赖对象通过构造函数的参数注入给依赖对象,并且在初始化对象的时候注入。
优点:
对象初始化完成后便可获得可使用的对象。
缺点:
当需要注入的对象很多时,构造器参数列表将会很长;
不够灵活。若有多种注入方式,每种方式只需注入指定几个依赖,那么就需要提供多个重载的构造函
数,麻烦。
二、 setter 方法注入
IoC Service Provider 通过调用成员变量提供的 setter 函数将被依赖对象注入给依赖类。
优点:
灵活。可以选择性地注入需要的对象。
缺点:
依赖对象初始化完成后由于尚未注入被依赖对象,因此还不能使用。
三、接口注入
依赖类必须要实现指定的接口,然后实现该接口中的一个函数,该函数就是用于依赖注入。该函数的参
数就是要注入的对象。
优点
接口注入中,接口的名字、函数的名字都不重要,只要保证函数的参数是要注入的对象类型即可。
缺点:
侵入行太强,不建议使用。
PS :什么是侵入行?
如果类 A 要使用别人提供的一个功能,若为了使用这功能,需要在自己的类中增加额外的代码,这就是
侵入性。

相关推荐
weixin_5375904519 分钟前
《Java编程入门官方教程》第八章练习答案
java·开发语言·servlet
CodeClimb1 小时前
【华为OD-E卷-最左侧冗余覆盖子串 100分(python、java、c++、js、c)】
java·python·华为od
Q_19284999061 小时前
基于Spring Boot的大学就业信息管理系统
java·spring boot·后端
xmh-sxh-13141 小时前
常用数据库类型介绍
java
single5941 小时前
【c++笔试强训】(第四十一篇)
java·c++·算法·深度优先·图论·牛客
1 9 J1 小时前
Java 上机实践11(组件及事件处理)
java·开发语言·学习·算法
爬菜2 小时前
java简单题目练习
java
bufanjun0012 小时前
JUC并发工具---ThreadLocal
java·jvm·面试·并发·并发基础
南宫生2 小时前
力扣-图论-70【算法学习day.70】
java·学习·算法·leetcode·图论