文章目录
前言
本篇介绍笔者关于Spring中IOC相关知识点的学习
一、IOC是什么?
关于IOC是什么,这里引用一句网上的定义进行阐述
IoC(Inversion of Control)控制反转,包含了两个方面:一、控制。二、反转
这里针对控制和反转解读如下
控制
当时对象对内部成员的控制权,比如对一个引用数据类型,通过new 对象的方式进行对象创建
反转
将对对象的控制权进行交出,这种控制权不再由当前对象进行管理,由其他(类,第三方容器)进行控制。例如上文的new 对象过程,交给第三方工厂通过反射的方式对对象进行创建
通过上面的简单介绍可知,其实IOC控制翻转的核心点,在于工厂模式和反射,当时在这里谈及这两个概念尚显抽象,具体的在本篇博客的后续部门我们进一步进行学习
二、IOC容器的原理
上文中我们提到,工厂模式是IOC中核心的设计模式,它能管理我们所有想要管理的对象和依赖关系
这里IOC容器的具体细节如下
- 原理就是通过Java的反射技术来实现的!通过反射我们可以获取类的所有信息(成员变量、类名等等等)!
- 再通过**配置文件(xml)**或者注解来描述类与类之间的关系
- 而后我们就可以通过这些配置信息和反射技术来构建出对应的对象和依赖关系了!
工厂模式在IOC中的具体体现
我们知道在一个类中要使用到另外一个类,我们可以通过创建另外一个类的实例,持有其的引用来进行操作,具体如下
public class A{
B b=new B();
b.use();
}
但是我们知道,这样直接操作,类A直接持有了对类B的引用,那么类A和类B之间的耦合是十分高的,那么我们是否有办法降低类A和类B之间的耦合呢?
答案是:工厂模式
我们可以在类A和类B之间设置一个工厂,从而达到解耦类A和类B的目的
public class A{
IocFactory iocf=new IocFactory();
B b=iocf.getB();
b.use();
}
public class IocFactory{
public B getB(){
return new B();
}
}
我们可以看到,这样做是达到了解耦类A和类B,但是我们让工厂和类B之间产生了耦合,那么我们能否更进一步,降低工厂和类B之间的耦合呢,答案是肯定的:我们可以通过外部配置文件引入,而后内部通过反射的方法获取到类,从而避免了直接创建类造成的耦合
public class A{
IocFactory iocf=new IocFactory();
B b=iocf.getB();
b.use();
}
public class IocFactory{
public B getB(){
String sb=...;//解析XML配置文件获取类名
B b = Class.forName(sb);
return b;
}
}
如此,我们便可以看到,类的创建并不在类中直接创建,而是通过进行更改XML配置文件,从而达到解析的目的
自动装配:IOC容器装配Bean
Spring工厂分类
在上文中,我们简单实现了一个工厂来将类A和类B之间的耦合进行降低,在Spring场景中,官方帮我们实现了相关的容器,从容器中的工厂获取类,而Spring中的工厂分为两类
- BeanFactory:相对底层,更多应用在Spring框架的实现
- ApplicationContext:在BeanFactory基础之上,面向使用Spring框架的开发者。
绝大多数情况下,我们倾向于使用ApplicationContext,例如Web开发中常用的WebApplicationContext
ApplicationContext和BeanFactory有何不同?
- ApplicationContext会利用Java反射机制自动识别出配置文件中定义的BeanPostProcessor、 InstantiationAwareBeanPostProcesso 和BeanFactoryPostProcessor后置器,并自动将它们注册到应用上下文中。而BeanFactory需要在代码中通过手工调用addBeanPostProcessor()方法进行注册
- ApplicationContext在初始化应用上下文的时候就实例化所有单实例的Bean。而BeanFactory在初始化容器的时候并未实例化Bean,直到第一次访问某个Bean时才实例化目标Bean。
Spring配置方法分类
而容器从外部读取类的配置(IOC容器装配),大致分为两种
- XML配置
- 注解配置
- Java Config
总体来说,我们更倾向于使用XML配置+注解的方式来完成类的配置
Spring依赖方式注入
- 属性注入:最常见的注入方式
- 构造函数注入
- 工厂方法注入
对象之间的关系
- 引用:借助Ref方式进行实现,也就是最常使用的
- 依赖:depend-on,比较难实现
- 继承:可能使用abstract和parent实现继承关系
三、IOC具体使用
XML配置
我们要基于XML进行类生成和解析,首先我们要有一个XML文件,并在其中配置类和类的信息
我们先书写一个类,实现相关接口和内容
public class Cat implements Animal {
private String name;
public void say() {
System.out.println("I am " + name + "!");
}
public void setName(String name) {
this.name = name;
}
}
在Spring中,我们在XML配置类和相关信息用的bean标签
<bean id="animal" class="phz.springframework.test.Cat">
<property name="name" value="kitty" />
</bean>
而后我们编写测试类,使用XML当中的配置进行类的创建和调用
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext(
"applicationContext.xml");
Animal animal = (Animal) context.getBean("animal");
animal.say();
}
最终输出结果
I am kitty!
在Spring中,容器先通过读取XML文件的形式,将键值对的值先保存在HashMap中,再调用反射方法,进行类的实例化生成,在类实例化后,调用类的setter的方法,将值进行注入
注解开发
除去XML配置文件的方式,Spring也支持基于注解去进行IOC开发
注解配置相关细节可查看这篇博客