Spring IoC
Ioc(Inversion of control:即控制反转)是一种设计思想,而不是一种具体的技术实现。IoC的思想就是将原本在程序中手动创建对象的控制权交给Spring框架来管理。
不过, IoC 并非 Spring 特有,在其他语言中也有应用。
为什么叫控制反转
-
控制: 指的是对象创建(实例化、管理)的权力;、
-
反转: 指的是将控制权交给外部环境(Spring框架、IoC容器)。
将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。 IoC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。
在实际项目中一个 Service 类可能依赖了很多其他的类,假如我们需要实例化这个 Service,你可能要每次都要搞清这个 Service 所有底层类的构造函数,这可能会把人逼疯。如果利用 IoC 的话,你只需要配置好,然后在需要的地方引用就行了,这大大增加了项目的可维护性且降低了开发难度。
在 Spring 中, IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个 Map(key,value),Map 中存放的是各种对象。
Spring 时代我们一般通过 XML 文件来配置 Bean,后来开发人员觉得 XML 文件来配置不太好,于是 SpringBoot 注解配置就慢慢开始流行起来。
IoC解决了什么问题
IoC 的思想就是两方之间不互相依赖,由第三方容器来管理相关资源。这样有什么好处呢?
-
对象之间的耦合度降低或者说依赖程度降低;
-
资源变的容易管理;比如你用 Spring 容器提供的话很容易就可以实现一个单例。
什么是依赖注入(Dependency Injection)
Dependency Injection。它是 spring 框架核心 IoC 的具体实现。
我们的程序在编写时,通过控制反转,把对象的创建交给了 spring,但是代码中不可能出现没有依赖的情况。IoC 解耦只是降低他们的依赖关系,但不会消除。例如:我们的业务层仍会调用持久层的方法。
那这种业务层和持久层的依赖关系,在使用 spring 之后,就让 spring 来维护了。
简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。
依赖注入的原理
所谓依赖注入,即在运行期由容器将依赖关系注入到组件之中。
讲的通俗点,就是在运行期,由Spring根据配置文件,将其他对象的引用通过组件的提供的setter方法进行设定。
Spring 大量引入了Java 的Reflection机制,通过动态调用的方式避免硬编码方式的约束,并在此基础上建立了其核心组件BeanFactory,以此作为其依赖注入机制的实现基础。
代码理解:
Class cls = Class.forName("net.xiaxin.beans.User");
Method mtd = cls.getMethod("setName",new Class[]{String.class});
Object obj = (Object)cls.newInstance();
mtd.invoke(obj,new Object[]{"Erica"});
return obj;
Object obj = Class.forName("net.xiaxin.beans.User").newInstance();
BeanWrapper bw = new BeanWrapperImpl(obj);
bw.setPropertyValue("name", "Erica");
System.out.println("User name=>"+bw.getPropertyValue("name"));
数据类型
能注入的数据类型:有三类
- 基本类型和String;
- 其他bean类型(在配置文件中或者注解配置过的bean);
- 复杂类型/集合类型。
Spring AOP
AOP:Aspect oriented programming 面向切面编程,AOP 是 OOP(面向对象编程)的一种延续。
下面我们先看一个 OOP 的例子。
例如:现有三个类,Horse、Pig、Dog,这三个类中都有 eat 和 run 两个方法。
通过 OOP 思想中的继承,我们可以提取出一个 Animal 的父类,然后将 eat 和 run 方法放入父类中,Horse、Pig、Dog通过继承Animal类即可自动获得 eat() 和 run() 方法。这样将会少些很多重复的代码。
OOP 编程思想可以解决大部分的代码重复问题。但是有一些问题是处理不了的。比如在父类 Animal 中的多个方法的相同位置出现了重复的代码,OOP 就解决不了。
/**
* 动物父类
*/
public class Animal {
/** 身高 */
private String height;
/** 体重 */
private double weight;
public void eat() {
// 性能监控代码
long start = System.currentTimeMillis();
// 业务逻辑代码
System.out.println("I can eat...");
// 性能监控代码
System.out.println("执行时长:" + (System.currentTimeMillis() - start)/1000f + "s");
}
public void run() {
// 性能监控代码
long start = System.currentTimeMillis();
// 业务逻辑代码
System.out.println("I can run...");
// 性能监控代码
System.out.println("执行时长:" + (System.currentTimeMillis() - start)/1000f + "s");
}
}
这部分重复的代码,一般统称为 横切逻辑代码。
横切逻辑代码存在的问题
- 代码重复问题
- 横切逻辑代码和业务代码混杂在一起,代码臃肿,不变维护
AOP 另辟蹊径,提出横向抽取机制,将横切逻辑代码和业务逻辑代码分离
代码拆分比较容易,难的是如何在不改变原有业务逻辑的情况下,悄无声息的将横向逻辑代码应用到原有的业务逻辑中,达到和原来一样的效果。
AOP 为什么叫面向切面编程
切 :指的是横切逻辑,原有业务逻辑代码不动,只能操作横切逻辑代码,所以面向横切逻辑
面 :横切逻辑代码往往要影响的是很多个方法,每个方法如同一个点,多个点构成一个面。这里有一个面的概念。
AOP 解决了什么问题
在不改变原有业务逻辑的情况下,增强横切逻辑代码,根本上解耦合,避免横切逻辑代码重复。
谈谈自己对于 AOP 的了解
AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。