IOC和AOP

IOC

IOC(控制反转):就是把创建和管理bean的过程交给第三方,这个第三方就是IOC容器。(也就是说它负责创建、管理bean,管理bean的生命周期,控制bean的依赖注入)。

因为,我们每次创建对象都很麻烦,所以使用Spring IOC容器来管理这些对象,需要的时候你就直接用,不用管它是怎么来的、什么时候要销毁,只管用就好了。

举个例子,就好像父母没时间管孩子,就把小朋友交给托管所,就安心的去上班而不用管孩子了。托儿所,就是第三方容器,负责管理小朋友的吃喝玩乐;父母,相当于程序员,只管接送孩子,不用管他们吃喝。

  • 控制是什么

    是bean的创建和管理,控制bean的生命周期。

  • 反转是什么

    把这个权力交给Spring容器,而不是自己去控制,就是反转。由之前的自己主动创建对象,变成现在被动接收别人给我们的对象的过程,这就是反转。

自己炒股、选股票的人就是主动投资,主动权掌握在自己的手中;而买基金的人就是被动投资,把主动权交给了基金经理,除非你把这个基金卖了,否则具体选哪些投资产品都是基金经理决定的。

依赖注入

  • 依赖注入(Dependency Injection):它是 Spring 框架核心 IOC 的具体实现。
  • 在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是代码中不可能出现没有依赖的情况。
  • IOC 解耦只是降低他们的依赖关系,但不会消除。例如:业务层仍会调用持久层的方法。
  • 那这种业务层和持久层的依赖关系,在使用 Spring 之后,就让 Spring 来维护了。
    简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。

IOC能带来什么好处

答:解耦,把对象之间的依赖关系,转成配置文件来管理,由 Spring IoC Container 来管理。

在项目中,底层的实现都是由很多个对象组成的,对象之间彼此合作实现项目的业务逻辑。但是,很多很多对象紧密结合在一起,一旦有一方出问题了,必然会对其他对象有所影响,所以才有了解藕的这种设计思想。

image-20221121144019680

image-20221121144046016

Spring中的八大模块

image-20221121144057699

每个「绿框」,对应一个模块,总共8个模块;「黑色包」,表示要实现这个模块的 jar 包。

既然说容器是 IoC 最重要的部分,那么 Spring 如何设计容器的呢?

答:使用 ApplicationContext,它是 BeanFactory 的子类,更好的补充并实现了 BeanFactory 的。

ApplicationContext 的里面有两个具体的实现子类,用来读取配置配件的:

  • ClassPathXmlApplicationContext - 从 class path 中加载配置文件,更常用一些;
  • FileSystemXmlApplicationContext - 从本地文件中加载配置文件,不是很常用,如果再到 Linux 环境中,还要改路径,不是很方便。

小结

通过 ApplicationContext 这个 IoC 容器的入口,用它的两个具体的实现子类,从 class path 或者 file path 中读取数据,用 getBean() 获取具体的 bean instance。

1
2
3
4
5
6
7
8
9
10
public void testBean3() {
// ApplicationContext context =
// new ClassPathXmlApplicationContext("bean4.xml");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
Orders orders = context.getBean("orders", Orders.class);
System.out.println("第四步 获取创建 bean 实例对象");
System.out.println(orders);
//手动让 bean 实例销毁
context.close();
}

那使用 Spring 到底省略了我们什么工作?

答:new 的过程。把 new 的过程交给第三方来创建、管理,这就是「解藕」。

AOP

AOP:面向切面编程,将那些与业务无关,却被业务模块共同调用的逻辑或责任(事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。

AOP 切面编程设计到的一些专业术语:

术语 含义
目标(Target) 被通知的对象
代理(Proxy) 向目标对象应用通知之后创建的代理对象
连接点(JoinPoint) 目标对象的所属类中,定义的所有方法均为连接点
切入点(Pointcut) 被切面拦截 / 增强的连接点(切入点一定是连接点,连接点不一定是切入点)
通知(Advice) 包括处理时机和处理内容。处理内容就是要做什么事,处理时机就是在什么时机执行处理内容(前,后)
切面(Aspect) 切入点(Pointcut)+通知(Advice)
Weaving(织入) 将通知应用到目标对象,进而生成代理对象的过程动作

切点:切点分为execution方式和annotation方式。前者可以用路径表达式指定哪些类织入切面,后者可以指定被哪些注解修饰的代码织入切面。

image-20221121144148718

为什么用AOP

Java是一个面向对象(OOP)的编程语言,但它有个弊端就是当需要为多个不具有继承关系的对象引入一个公共行为时,例如日志记录、统一的异常处理、事务管理(在调用方法前开启事务,调用方法后关闭事务)、统计等功能,只能在每个对象里都引用公共行为,这样做不便于维护,而且有大量重复代码,AOP的出现弥补了OOP的这点不足。

image-20221121144210983

有多少个业务操作,就要写多少重复的校验和日志记录代码,这显然是无法接受的。当然用面向对象的思想,可以把这些重复的代码抽离出来,写成公共方法,就是下面这样:

image-20221121144222459

代码冗余和可维护性的问题得到了解决,但每个业务方法中依然要依次手动调用这些公共方法,也是略显繁琐。 有没有更好的方式呢?有的,那就是AOP,AOP将权限校验、日志记录等非业务代码完全提取出来,与业务代码分离,并寻找节点切入业务代码中

image-20221121144238833


IOC和AOP
http://example.com/2022/11/21/IOC和AOP/
作者
zlw
发布于
2022年11月21日
许可协议