Spring IOC学习

  1. 1. Spring IOC学习
    1. 1.1. Spring IOC
    2. 1.2. Spring IOC加载流程
      1. 1.2.1. 流程
      2. 1.2.2. FactoryBean和BeanFactory区别
      3. 1.2.3. 区分FactoryBean和普通Bean
      4. 1.2.4. ApplicationContext
    3. 1.3. bean的生命周期
    4. 1.4. 总结

Spring IOC学习

Spring IOC

这里需要注意的是,IOC和Spring IOC不能混为一谈,IOC是一种概念和设计思路,Spring实现了IOC的思想,是IOC的实践。

我们通常提到的Spring IOC,实际上是指Spring框架提供的IOC容器实现(IOC Container)

IOC叫做控制反转,另一种说法是依赖注入。

IOC的作用简单来说,就是控制对象的创建和销毁。控制和销毁本来是由用户控制的,用了IOC之后用户只需要去关注业务需求。

反转的概念:

正转指的是对象去找实例(Object o = new Object();),反转就是实例去找对象,通过容器去找对象。

依赖:

在spring项目中,将对象理解为Bean,也可以叫bean对象,这个bean和容器之间有个依赖关系,bean对象的创建是依赖容器的,就好像孩子依赖父母一样,孩子不能自己生出自己,需要父母的合作才能出生,这里的孩子就是bean,父母就是容器

注入:

通过容器注入了bean对象,而且这个过程是自动化的,也就是说容器会自动找到和bean对象匹配的类型实例注入到对象中;

Spring IOC加载流程

流程

1646646389223.png

1、先是通过BeanDefinitionReader读取配置文件,生成bean的信息。BeanDefinition对象是完整的bean定义信息。这里只是存储bean的定义信息还没有实例化bean对象。

2、在 BeanDefinition 和 完整BeanDefinition 中间通过一个后置增强器,可以对bean的定义信息进行统一修改,只需要实现 BeanFactoryPostProcessor 接口即可,这个后置增强器是可以有多个的,你只要在不同的类实现多个 BeanFactoryPostProcessor 接口就会执行多次,就像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.Spring.Boot.init;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
/**
* 扩展方法--后置增强器(可修改bean的定义信息)
*/
@Component
public class ExtBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// BeanDefinition studentService = beanFactory.getBeanDefinition("studentService");
System.out.println("扩展方法--可进行修改beanDefinition的定义信息");
}
}

3、得到完整BeanDefinition之后就可以进行创建对象了,这整个过程被称为 bean 的生命周期,也就是从实例化到销毁的过程;

FactoryBean和BeanFactory区别

BeanFactory直译是生产Bean的工厂,在Spring中就是容器,常用的ApplicationContext就是它的一个继承类.而FactoryBean顾名思义就是一个bean,但这个bean和普通bean有点不一样。

区分FactoryBean和普通Bean

​ Spring中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean即FactoryBean,这两种Bean都被容器管理。工厂Bean是实现了org.springframework.beans.factory.FactoryBean接口的Bean,从ApplicationContext的getBean()方法获取的对象不是该类的一个实例,而是该类的getObject()方法所返回的对象。

 当我们需要获取FactoryBean实例本身而不是它所产生的bean,则要使用&符号。

 比如,现有FactoryBean,id为“playerBean”,在容器上调用getBean(“playerBean”)将返回FactoryBean产生的bean。调用getBean(“&playerBean”)将返回FactoryBean它本身的实例。

ApplicationContext

1646654275291.png

接口 BeanFactory 和 ApplicationContext 都是用来从容器中获取 Spring beans 的,但是,他们二者有很大不同

如果说BeanFactory是Spring的心脏,那么ApplicationContext就是完整的躯体了。

ApplicationContext继承了BeanFactory(ListableBeanFactory, HierarchicalBeanFactory),所以它拥有更完善的功能,支持大型的业务。

两者获取bean的区别,举例

Beans.xml

1
2
3
4
5
6
7
8
9
<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id = "helloWorld" class = "com.zoltanraffai.HelloWorld">
<property name = "message" value = "Hello World!"/>
</bean>
</beans>

BeanFactory 和 ApplicationContext怎么获取他?

BeanFactory:

1
2
3
4
5
6
7
8
9
10
11
 import org.springframework.core.io.ClassPathResource;  
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.xml.XmlBeanFactory;
public class HelloWorldApp{
public static void main(String[] args) {
XmlBeanFactory factory = new XmlBeanFactory (new ClassPathResource("beans.xml"));
HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");
obj.getMessage();
}
}

ApplicationContext:

1
2
3
4
5
6
7
8
9
10
11
import org.springframework.core.io.ClassPathResource;  
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.xml.XmlBeanFactory;
public class HelloWorldApp{
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
}
}

看起来是差不多,但他们的加载方式是不同的。

BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,这样,我们就不能发现一些存在的Spring的配置问题。而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误。 相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。

bean的生命周期

1646654683754.png

总结

简单的学一下,主要是看这位大神的文章,从源码的角度讲,写的特别详细

https://javadoop.com/post/spring-ioc