【Spring】IoC容器 - 依赖查找
前言
上一篇文章已经学习了【IoC的主要实现策略】有2种:
1、依赖查找
2、依赖注入
这里稍加详细的介绍一下依赖查找
1.依赖查找的方式
依赖查找的方式可以以多种维度来划分:
1.按名称/类型/注解查找
2.按单一类型/集合类型/层次性依赖查找
3.延迟查找、实时查找
1.1维度一
1.1.1根据 Bean 名称查找
实时
private static void lookupInRealTime(BeanFactory beanFactory) {
User user = (User) beanFactory.getBean("user");
System.out.println("实时查找:" + user);
}
延迟
private static void lookupInLazy(BeanFactory beanFactory) {
ObjectFactory<User> objectFactory = (ObjectFactory<User>) beanFactory.getBean("objectFactory");
User user = objectFactory.getObject();
System.out.println("延迟查找:" + user);
}
这里省略了一个名为user的bean
<bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
<property name="targetBeanName" value="user"/>
</bean>
1.1.2根据 Bean 类型查找
private static void lookupByType(BeanFactory beanFactory) {
User user = beanFactory.getBean(User.class);
System.out.println("实时查找:" + user);
}
1.1.3根据 Java注解查找
private static void lookupByAnnotationType(BeanFactory beanFactory) {
if (beanFactory instanceof ListableBeanFactory) {
ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
Map<String, User> users = (Map) listableBeanFactory.getBeansWithAnnotation(Super.class);
System.out.println("查找标注 @Super 所有的 User 集合对象:" + users);
}
}
1.2维度二
1.2.1单一类型查找
单一类型的查找是基于BeanFactory这个接口来实现的。
- 根据Bean名称查找
- getBean(String)
- 根据Bean类型查找
- Bean实时查找
- getBean(Class)
- Bean延迟查找 (Spring5.1)
- getBeanProvider(Class)
- getBeanProvider(ResolvableType)
- Bean实时查找
- 根据Bean名称+类型查找
- getBean(String, Class)
1.2.2集合类型查找
集合类型的查找是基于ListableBeanFactory这个接口来实现的。
- 根据Bean类型查找
- 获取同类型Bean名称列表
- getBeanNamesForType(Class)
- getBeanNamesForType(ResolvableType) [Spring4.2]
- 获取同类型Bean实例列表
- getBeansOfType(Class)以及它的重载方法
- 获取同类型Bean名称列表
- 根据注解类型查找
- Spring3.0获取标注类型Bean名称列表
- getBeanNamesForAnnotation(Class<? extends Annotation>)
- Spring3.0获取标注类型Bean实例列表
- getBeansWithAnnotation(Class<? extends Annotation>)
- Spring3.0获取指定名称 + 标注类型Bean实例
- findAnnotationOnBean(String, Class<? extends Annotation>)
- Spring3.0获取标注类型Bean名称列表
1.2.3层次性查找
层次性类型的查找是基于HierarchicalBeanFactory这个接口来实现的。
这里的层次性查找是有一点类似于类加载的双亲委派,但是它的实现是需要依赖于下面接口的方法:
public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {
/**
* Set the parent of this bean factory.
* <p>Note that the parent cannot be changed: It should only be set outside
* a constructor if it isn't available at the time of factory instantiation.
* @param parentBeanFactory the parent BeanFactory
* @throws IllegalStateException if this factory is already associated with
* a parent BeanFactory
* @see #getParentBeanFactory()
*/
void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;
实现的基本逻辑就是:
1.获取到子BeanFactory
2.创建一个ParentBeanFactory
3.设置父子关系
4.获取bean的时候,先判断其ParentBeanFactory是否存在,不存在,则判断子BeanFactory是否存在。使用递归。
这里我不是很清楚层次性依赖查找有什么用处,目前的项目业务中一般只会有默认的Spring创建的BeanFactory。
1.3维度三
1.3.1延迟查找
延迟查找可以用过2个接口实现:
1、ObjectFactory
2、ObjectProvider
其中ObjectProvider继承了ObjectFactory:
public interface ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {
这里的延迟查找:
基本原理就是
1.通过AbstractApplicationContext接口的方法:getBeanProvider(Class<T> requiredType)获取到一个ObjectFactory或ObjectProvider的实例
2.当真正需要使用指定类型【上一步的requiredType】的实例的时候,调用ObjectFactory实例【上一步的返回值】的T getObject(),在第二步才是真正的执行依赖查找。
示例
private static void lookupByObjectProvider(AnnotationConfigApplicationContext applicationContext) {
ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class); //第一步
System.out.println(objectProvider.getObject()); //第二步,这一步跟进源码,可以知道这一步是怎么实际查找的。
//DependencyObjectProvider.java
}
非延迟初始化Bean也能实现延迟查找:
也就是说 即时初始化的bean也能实现延迟查找。
实际的ObjectProvider实现类一般是在DefaultListableBeanFactory.java中的内部类DependencyObjectProvider.java:

1.3.2实时查找
除了延迟查找,基本都是实时查找,没什么好说的。
2.依赖查找的安全性

3.Spring内建依赖
Spring默认容器启动的时候,有一些内置的依赖,这些依赖是帮助spring实现某些基础功能所需的。算是Spring给自身的扩展和增强。



4.依赖查找的经典异常

【Spring】IoC容器 - 依赖查找的更多相关文章
- Spring IOC容器装配Bean_基于注解配置方式
bean的实例化 1.导入jar包(必不可少的) 2.实例化bean applicationContext.xml(xml的写法) <bean id="userDao" cl ...
- 【Spring】IoC容器 - 依赖来源
前言 上一篇文章已经学习了[依赖注入]相关的知识,这里详细的介绍一下[依赖来源]. 依赖来源 我们把依赖来源分为依赖查找的来源和依赖注入的来源分别讨论. 依赖查找的来源 1. Spring BeanD ...
- Ioc容器依赖注入-Spring 源码系列(2)
Ioc容器依赖注入-Spring 源码系列(2) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostPr ...
- Spring IOC 容器源码分析 - 循环依赖的解决办法
1. 简介 本文,我们来看一下 Spring 是如何解决循环依赖问题的.在本篇文章中,我会首先向大家介绍一下什么是循环依赖.然后,进入源码分析阶段.为了更好的说明 Spring 解决循环依赖的办法,我 ...
- Spring源码之IOC容器创建、BeanDefinition加载和注册和IOC容器依赖注入
总结 在SpringApplication#createApplicationContext()执行时创建IOC容器,默认DefaultListableBeanFactory 在AbstractApp ...
- 纯注解快速使用spring IOC容器
使用spring的ioc容器实现对bean的管理与基本的依赖注入是再经典的应用了.基础使用不在详述. 这里主要介绍下使用注解实现零配置的spring容器.我相信你也会更喜欢使用这种方式.Spring ...
- Spring IOC容器基本原理
2.2.1 IOC容器的概念IOC容器就是具有依赖注入功能的容器,IOC容器负责实例化.定位.配置应用程序中的对象及建立这些对象间的依赖.应用程序无需直接在代码中new相关的对象,应用程序由IOC容器 ...
- Spring IOC 容器源码分析 - 填充属性到 bean 原始对象
1. 简介 本篇文章,我们来一起了解一下 Spring 是如何将配置文件中的属性值填充到 bean 对象中的.我在前面几篇文章中介绍过 Spring 创建 bean 的流程,即 Spring 先通过反 ...
- Spring IOC 容器源码分析 - 获取单例 bean
1. 简介 为了写 Spring IOC 容器源码分析系列的文章,我特地写了一篇 Spring IOC 容器的导读文章.在导读一文中,我介绍了 Spring 的一些特性以及阅读 Spring 源码的一 ...
随机推荐
- redis未授权getshell的4种方式
前言 redis未授权漏洞或弱口令一直是很有用的渗透突破口,最近正好闲的无事就拿redis来测试一些,做一个简单的收集,方便自己日后的回顾. 漏洞描述 Redis 默认情况下,会绑定在 0.0.0.0 ...
- key存活时间和五个类型通用的一些指令操作
一.设置key的存活时间 1.失效后 ttl 是 -2,get返回 null : 2.不设置存活时候 ttl 返回是 -1: 二.查找指令和删除指令.重命名key.查看key类型 1.模糊查询 2.严 ...
- 全网唯一正常能用的centos7 安装mysql5.7.35 22 33 25
CentOS7.4用yum安装并配置MySQL5.7 1.配置YUM源 下载MySQL源安装包 wget http://dev.mysql.com/get/mysql57-community-re ...
- Spring5框架学习笔记
Spring5学习笔记 介绍: 1.引入相应jar包 导入: ps:网上下载教程: https://repo.spring.io/release/org/springframework/spring/ ...
- jquery 设置django全局token
通过JQUEYR中的ajaxSetup,来设置django中的token,即不需要再每次都去引用: 第一步: 先django中的html中设置 {% csrf_token %} 第二步: 新一个js ...
- JavaScript --css样式
1.JavaScript显示隐藏控制 隐藏:display:none; 显示:display:block; 参考链接:https://blog.csdn.net/sleepwalker_1992/ar ...
- Fabric SSH链接时关于找不到主机的问题
先上一段简单的fabric代码: from __future__ import with_statementfrom fabric.api import *env.user = 'zhangsan'e ...
- python爬虫与mysql,mongobd(1)(2)第一个视频python_pymysql 安装与使用类型,import解决 问题之模块引ru 就是解决你的问题
import pymysql.cursors ''' 1.创建连接 2.创建游标 3.执行sql 5.接受结果 ''' # 1.连接 connection =pymysql.Connect( # 域名 ...
- P4234-最小差值生成树【LCT】
正题 题目链接:https://www.luogu.com.cn/problem/P4234 题目大意 给出\(n\)个点\(m\)条边的一张图.求一棵生成树使得最大边权减去最小边权最小. \(1\l ...
- AT4144-[ARC098D]Donation【Kruskal重构树,dp】
正题 题目链接:https://www.luogu.com.cn/problem/AT4144 题目大意 \(n\)个点\(m\)条边的一张无向联通图,每个点有两个值\(a_i,b_i\).表示经过该 ...