Spring笔记(3):IOC容器
创始人
2024-05-29 08:35:42
0

1、IOC容器是什么?
IOC容器是Spring容器的重要组成部分,它具有依赖注入功能,负责实例化、定位、配置Bean对象,并建立对象之间依赖。
通过配置(Metadata),由Spring容器创建对象,这个配置是对应POJO对象类的属性进行注入,创建完毕后发送给ApplicationContext容器进行渲染。

在这里插入图片描述


2、两种Spring常见IOC容器

  • Spring BeanFactory容器:是一种最简单的容器,通过BeanFactory接口定义。

  • Spring Application容器:是一种企业级容器,通过ApplicationContext接口定义

因为ApplicationContext容器包括BeanFactory的功能,所以通常不使用BeanFactory。
BeanFactory优点也明显,数据吞吐量和速度是优秀的。


3、Spring BeanFactory容器
Spring有大量对BeanFactory接口的实现,其最常使用的是XmlBeanFactory类。
XmlBeanFactory——功能是读取XML文件的配置数据形成BeanFactory
我们从介绍上也能看出来,XmlBeanFactory的数据来源是XML配置,并且在声明它时需要加载XML文件。


User.java

public class User {private String uid;private String uname;public User() {}public User(String uid, String uname) {this.uid = uid;this.uname = uname;}public String getUid() {return uid;}public void setUid(String uid) {this.uid = uid;}public String getUname() {return uname;}public void setUname(String uname) {this.uname = uname;}@Overridepublic String toString() {return "User{" +"uid='" + uid + '\'' +", uname='" + uname + '\'' +'}';}
}

Main.java

public class Main {public static void main(String[] args) {XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("Beans.xml"));User user = (User) factory.getBean("user");System.out.println(user.toString());}
}

Beans.xml


bean-id: bean对象的唯一编号bean-name:bean对象的名称bean-class:bean注入对象property-name:注入对象属性名property-value:注入对象属性值

我们需要什么依赖呢?
pom.xml

	org.springframeworkspring-beans5.3.18org.springframeworkspring-core5.3.20

一定要注意版本兼容问题,会报异常哦~

输出结果

User{uid='123123', uname='这是我的名字'}

4、Spring ApplicationContext容器

  • Application Context是BeanFacctory的子接口,也称为Spring上下文。
  • 可以加载配置文件中定义的bean,在请求状态下分配bean对象。
  • 另外增加了企业所需要的功能,例如从属性文件中解析文本和传递事件给监听器。
  • 通过context.ApplicationContext 接口定义。

加载XML文件的三种方式

  • FileSystemXmlApplicationContext: 通过扫描XML文件绝对路径进行载入
  • ClassPathXmlApplicationContext: 通过扫描XML文件相对路径进行载入
  • XmlWebApplicationContext: 在一个web应用程序范围内加载XML文件

需要ApplicationContext依赖——Spring Context
pom.xml

        org.springframeworkspring-context5.3.18

要注意版本兼容问题

Main.java

public class Main {public static void main(String[] args) {ApplicationContext context = new FileSystemXmlApplicationContext("D:/JavaWebProgram/BeanDemo/src/main/resources/Beans.xml");User user = (User) context.getBean("user");System.out.println("绝对路径下的Bean:"+user.toString());context = new ClassPathXmlApplicationContext("Beans.xml");user = (User) context.getBean("user");System.out.println("相对路径下的Bean:"+user.toString());}
}

输出结果

绝对路径下的Bean:User{uid='123123', uname='这是我的名字'}
相对路径下的Bean:User{uid='123123', uname='这是我的名字'}

5、Spring Bean

5.1 Spring Bean定义

Bean对象是构成应用程序的单元,被Spring IOC容器管理。
Bean定义包含配置元数据


可以配置什么元数据?

  • Bean的创建
  • Bean的生命周期
  • Bean的依赖关系

Bean的属性

属性描述
class这个属性是强制性的,并且指定用来创建 bean 的 bean 类。
name这个属性指定唯一的 bean 标识符。在基于 XML 的配置元数据中,你可以使用 ID 和/或 name 属性来指定 bean 标识符。
scope这个属性指定由特定的 bean 定义创建的对象的作用域,它将会在 bean 作用域的章节中进行讨论。
constructor-arg它是用来注入依赖关系的,并会在接下来的章节中进行讨论。
properties它是用来注入依赖关系的,并会在接下来的章节中进行讨论。
autowiring mode它是用来注入依赖关系的,并会在接下来的章节中进行讨论。
lazy-initialization mode延迟初始化的 bean 告诉 IoC 容器在它第一次被请求时,而不是在启动时去创建一个 bean 实例。
initialization 方法在 bean 的所有必需的属性被容器设置之后,调用回调方法。它将会在 bean 的生命周期章节中进行讨论。
destruction 方法当包含该 bean 的容器被销毁时,使用回调方法。它将会在 bean 的生命周期章节中进行讨论。

Bean与Spring容器的关系

  • 步骤1: 扫描XML,扫描注解,配置类获取元数据
  • 步骤2: Spring容器定义注册表
  • 步骤3: Bean实现类实例化Bean对象,并装载入缓存池中
  • 步骤4: 应用程序调取缓存池中的Bean对象
    在这里插入图片描述

Spring配置元数据

有哪些方法可以配置元数据给Spring容器

  • 基于XML的配置文件(
  • 基于注解的配置(@Autowire)
  • 基于Java的配置(@Configuration)

5.2 Spring Bean 作用域


scope有哪些作用域值呢?

  • singleton: Bean以单例模式存在,即getBean时,是同一个Bean对象
  • prototype: Bean以原型模式存在,即getBean时,是不同的Bean对象
  • request: 每次HTTP请求创建新的Bean,仅适用于WebApplicationContext环境
  • session: 同一个Session会话共享一个Bean,不同Session使用不同Bean,仅适用于WebApplicationContext环境
  • global-session: 应用于Portlet应用环境,仅适用于WebApplicationContext环境

什么是Portlet?
它是一种基于Java的web组件化网页,看起来有点复古,支持Servlet进行HTTP的请求反馈。


singleton 作用域
singleton是默认作用域,如果你不指定scope,就只有一个Bean对象给你蹂躏。
singleton的创建时间是与容器一同被创建。

Main.java

public class Main {public static void main(String[] args) {ApplicationContext context;User user1,user2;context = new ClassPathXmlApplicationContext("Beans.xml");user1 = (User) context.getBean("user");System.out.println("user1:"+user1);user1.setUname("真差劲诶");user2 = (User) context.getBean("user");System.out.println("user2:"+ user2);}
}

输出结果

user1:User{uid='123123', uname='这是我的名字'}
user2:User{uid='123123', uname='真差劲诶'}

我们可以看到,在user1的set方法后,获取到的user2就是set后的数据,即这个bean是同一个对象。

prototype 作用域

prototype是一个原型模式下作用域,能够对应多实例,可以类比父类,getBean出来的则是一个它的子类,每一次get都是不同的子类。



我们在刚刚的程序文件上,只改动scope的值
输出结果

user1:User{uid='123123', uname='这是我的名字'}
user2:User{uid='123123', uname='这是我的名字'}

我们可以清晰的知道,它们是两个不同的对象,所以才不会受到user1对象的set方法影响。

5.3 Spring Bean 生命周期

  • Bean的定义
  • Bean的初始化
  • Bean的使用
  • Bean的销毁

两种重要生命周期

	init-method:调取初始化方法destroy-method:调取销毁方法

初始化回调与销毁回调

InitalizingBean接口实现初始化回调方法
DestroyBean接口实现销毁回调方法

User.java

package org.example.POJO;import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;/*** 包名:BeanDemo* 作者:章恩光* 时间:2023/3/5 22:09 周日*/
public class User implements InitializingBean, DisposableBean {private String uid;private String uname;public User() {}public User(String uid, String uname) {this.uid = uid;this.uname = uname;}public String getUid() {return uid;}public void setUid(String uid) {this.uid = uid;}public String getUname() {return uname;}public void setUname(String uname) {this.uname = uname;}public void init(){System.out.println("Bean is going through init");}public void destroy(){System.out.println("Bean will destroy now");}@Overridepublic String toString() {return "User{" +"uid='" + uid + '\'' +", uname='" + uname + '\'' +'}';}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("UserBean has created。");}
}

Beans.xml

	

Spring容器执行顺序:

  • 步骤1: 注入对象实现InitializingBean, DisposableBean接口,需要编写的方法有init(),destroy(),afterPrepartiesSet()
  • 步骤2:

提供默认初始化和销毁方法



5.4 Spring Bean 后置处理器

  • 什么是Bean 后置处理器? Bean的拓展坞,在初始化前后进行处理

  • 怎么实现后置处理器? BeanPostProcessor接口定义回调方法

    • 可以用该方法进行优化Spring容器启动效率,例如编写自己的实例化逻辑,依赖解析逻辑;
    • 可以在Spring容器中插入若干个BeanPostProcessor实现实例化,配置和初始化一个bean之后实现自定义逻辑回调方法;
    • 可以配置多个BeanPostProcessor接口,通过设置BeanPostProcessor.Ordered接口提供的order属性来控制BeanPostProcessor顺序。

注意:

  • Application自动检测后置处理器实现的bean,再通过容器创建bean。
  • 自定义接口实现类中,必须实现的方法:
    • BeanPostProcessor.postProcessBeforeInitialization(Object, String)​ ​
    • BeanPostProcessor.postProcessAfterInitialization(Object, String)

初始化类InitUser.java

public class InitUser implements BeanPostProcessor {@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("AfterInitialization:"+beanName);return bean;}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("BeforeInitialization:"+beanName);return bean;}
}

Beans.xml


加载初始化后置处理器

输出结果

BeforeInitialization:user
UserBean has created。
Bean is going through init
AfterInitialization:user
username:这是我的名字

执行过程顺序:

  • 后置器BeforeInitialization执行
  • Bean注册表创建
  • Bean执行init()方法
  • 后置器AfterInitialization执行
  • 使用Bean
  • Bean执行destroy()方法

5.5 Spring Bean 定义继承

bean定义可以包含很多配置信息:包括构造函数参数属性值初始化方法静态工厂方法名等等

继承bean可以重写值,或添加值。

它们之间的关系:与抽象类继承类的关系相同。



Bean 定义模板



相关内容

热门资讯

安卓系统的几大组件,组件架构与... 你有没有发现,你的安卓手机里藏着许多神奇的“小精灵”呢?它们默默无闻地工作,让你的手机变得如此强大和...
安卓系统关闭app流量,轻松关... 手机里的APP们是不是有时候让你觉得流量消耗得有点儿太快了呢?别急,今天就来教你几招,让你的安卓手机...
安卓系统无尽之海,安卓系统中的... 安卓系统,无尽之海中的航行者想象你正站在一望无际的海洋边,海风轻拂,波光粼粼。这片海洋,深邃而神秘,...
苹果系统用安卓主题,安卓主题完... 你有没有想过,把苹果系统的简洁优雅和安卓的丰富个性结合起来呢?想象你的iPhone界面突然变得五彩斑...
ios系统和安卓系统的体验,系... 你有没有发现,现在手机市场上两大巨头——iOS系统和安卓系统,就像是一对双胞胎,各有各的特色,让人挑...
安卓刷机Linux系统,深度解... 你有没有想过,你的安卓手机其实可以变身成一个强大的Linux系统?没错,就是那个让无数程序员为之疯狂...
安卓系统卫士那个好,哪款更胜一... 手机里的安卓系统卫士,就像是我们的私人保镖,时刻守护着我们的手机安全。那么,这么多卫士中,哪个才是最...
安卓手机互换苹果系统,跨界体验... 你有没有想过,把安卓手机换成苹果系统,会是怎样的体验呢?想象你的手机瞬间变身,从安卓的海洋跳进了苹果...
共享系统推荐安卓游戏,共享系统... 你有没有发现,最近手机里的游戏推荐越来越贴心了?没错,就是那个神奇的共享系统,它就像你的私人游戏顾问...
新疆安卓系统广告机,智能展示新... 新疆安卓系统广告机:数字时代的弄潮儿在数字化浪潮席卷全球的今天,智能手机已成为我们生活中不可或缺的一...
tissot怎么配对安卓系统,... 你有没有想过,一块手表不仅仅是一件饰品,更是一种时尚的宣言呢?Tissot,这个瑞士手表品牌,以其优...
苹果系统真的不如安卓,苹果系统... 你有没有想过,为什么苹果系统总是被捧得那么高,而安卓系统却总是被说成“不如”呢?今天,咱们就来聊聊这...
安卓系统短信横幅关闭,享受清爽... 你是不是也和我一样,最近发现安卓手机的短信横幅功能有点烦人呢?每次收到短信,屏幕上就会飘来一条横幅,...
手机刷安卓11系统,系统革新与... 你有没有发现,最近你的手机好像变得有点不一样了?没错,就是那个一直默默陪伴你的安卓系统,它悄悄地升级...
安卓系统 漂移游戏下载,速度与... 你有没有想过,在手机上玩一款能让你心跳加速、手忙脚乱的游戏?今天,就让我带你走进安卓系统中的神秘世界...
安卓4修改系统语言,轻松切换多... 你有没有想过,手机里的语言设置竟然也能成为个性展示的小细节呢?没错,就是那个看似不起眼,实则能让你瞬...
安卓版pc端系统,跨越平台界限... 你有没有想过,你的安卓手机里的应用,竟然可以在电脑上无缝运行?没错,这就是安卓版PC端系统的魅力所在...
安卓7车机系统,科技与安全的完... 你有没有发现,现在的汽车越来越智能了?没错,我说的就是那些内置了安卓7车机系统的家伙们。想象当你坐在...
王者荣耀安卓系统区别,深度揭秘... 你有没有发现,玩王者荣耀的时候,安卓系统的手机和苹果系统的手机,感觉就像是两个不同的世界呢?今天,就...
盒子电视安卓9系统,畅享智能新... 亲爱的读者们,你是否曾为拥有一台功能强大、系统流畅的电视而心动?今天,我要给你介绍一款特别受欢迎的盒...