目录

BeanFactory & ApplicationContext IOC 容器概述

BeanFactoryAware 获取 BeanFactory

ApplicationContextAware 获取 ApplicationContext

直接注入获取 IOC 容器

@Bean 添加实例时参数注入容器

启动类 Main 方法中获取 IOC 容器

WebApplicationContextUtils 工具类获取IOC容器


BeanFactory & ApplicationContext IOC 容器概述

1、org.springframework.beans.factory.BeanFactory 是一个 Factory(工厂),也就是 IOC 容器/对象工厂,Spring 中所有的 bean 都是由 BeanFactory(也就是IOC容器)来进行管理的。

2、可以使用 @Autowired、@Resource 注解来从 Spring 容器中自动获取实例,也可以手动从容器中获取。无论是以前用 xml 配置文件来配置 <bean>、还是后来使用 @Bean、@Component ...注解,都是为了将对象交由 Spring 容器管理。

3、BeanFactory 作为 IOC 功能的顶级接口,提供了各种不同的实现,IOC 作为 Spring 的核心功能之一,所以这些 API 也是很常见的。

4、ApplicationContext 是 BeanFactory 的扩展功能得到了进一步增强,比如更易与 Spring AOP 集成、消息资源处理(国际化处理)、事件传递及各种不同应用层的 context 实现(如针对 web 应用的 WebApplicationContext)。

5、只要获取了 BeanFactory 或 ApplicationContext,则可以随意获取容器中的任意实例(bean),推荐使用 ApplicationContext 。

//这两行代码一定不陌生
BeanFactory bf = new ClassPathXmlApplicationContext("student.xml");
Student studentBean = (Student) bf.getBean("studentBean");
//BeanFactory 在 spring-beans-x.x.x.RELEASE.jar 包下
BeanFactory 接口常用方法
Object getBean(String name)

返回指定名称的 bean 实例,默认为单例。

如果没有具有指定名称的bean,则引发 NoSuchBeanDefinitionException

如果无法获取bean,则抛出 BeansException

<T> T getBean(String name, Class<T> requiredType)

在 get(String name) 的基础上加上了requiredType类型限制,可以是接口或超类。

如果bean不是所需类型,则引发BeannotofRequiredTypeException

<T> T getBean(Class<T> requiredType)

返回唯一匹配给定对象类型的bean实例(如果有).

bean 必须匹配参数RequiredType类型,可以是接口或超类

如果找到给定类型的多个bean,则引发nouniqueBeanDefinitionException

boolean containsBean(String name) 返回是否存在具有给定名称的bean.
boolean isSingleton(String name) 返回此bean是否是单例。如果没有具有给定名称的bean,则引发nosuchbeanDefinitionException
Class<?> getType(String name)

返回bean的类型,如果不能确定,则返回 NULL。

如果没有具有给定名称的bean,则引发nosuchbeanDefinitionException

BeanFactoryAware 获取 BeanFactory

1、对于 BeanFactory 管理的 Bean,怎么获取它然后使用呢?使用 @Autowired、@Resource 注解来注入是最常见的操作,也是必须掌握的技能。

2、 使用 @Autowired、@Resource 注解的类自己首先必须是 Spring 组件 @Component 才能注入,而有时候想在项目中的任意位置都能获取容器中的实例进行使用,比如想在某个 XxxUtils 中使用某个 @Service 标识的实例,这时把 XxxUtils 标识为 @Component ,然后使用 @Resource 注入实例,这种方式看起来没有使用代码直接从 BeanFactory 容器中获取实例方便。

3、显然只要拿到了 BeanFactory 对象,就可以使用它的 getBean 方法从容器中获取 bean 实例,而获取 BeanFactory 实例的一个最简单的方式就是实现 BeanFactoryAware 接口。

package org.springframework.beans.factory;
// BeanFactoryAware 接口只要一个方法
public interface BeanFactoryAware extends Aware {/**初始化回调方法,spring 会自动将 BeanFactory 注入进行,我们接收之后即可使用 BeanFactory*/void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}

4、自定义一个工厂类/工具类/助手类 实现 BeanFactoryAware 接口,有了它,则可以在项目中的任意位置传入 bean 名称或者类型来轻松获取容器中的实例(Jdk 8 + Spring Boot 2.1.6):

/*** 1、实现 BeanFactoryAware 接口,重写 setBeanFactory(BeanFactory beanFactory)* 2、本类必须是 Spring 组件,所以加上 @Component 注解* 3、spring 容器启动实例化本类的时候,会自动执行回调方法 setBeanFactory(BeanFactory beanFactory) 将 BeanFactory 注入* 4、获取了 BeanFactory 之后,则可以使用它的任意方法了,比如各种 getBean*/
@Component
public class BeanFactoryHelper implements BeanFactoryAware {private static BeanFactory beanFactory;/*** 重写 BeanFactoryAware 接口的方法* @param beanFactory :参数赋值给本地属性之后即可使用 BeanFactory* @throws BeansException*/@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {this.beanFactory = beanFactory;}/*** 根据名称获取容器中的对象实例* @param beanName :注入的实例必须已经存在容器中,否则抛异常:NoSuchBeanDefinitionException* @return*/public static Object getBean(String beanName) {return beanFactory.getBean(beanName);}/*** 根据 class 获取容器中的对象实例* @param requiredType :被注入的必须已经存在容器中,否则抛异常:NoSuchBeanDefinitionException* @param <T>* @return*/public static <T> T getBean(Class<T> requiredType) {return beanFactory.getBean(requiredType);}/*** 判断 spring 容器中是否包含指定名称的对象* @param beanName* @return*/public static boolean containsBean(String beanName) {return beanFactory.containsBean(beanName);}//其它需求皆可参考 BeanFactory 接口和它的实现类
}

src/main/java/com/wmx/jdbc_template_app/helper/BeanFactoryHelper.java · 汪少棠/jdbc_template_app - Gitee.com

4、控制层代码演示如下:

    /*** BeanFactoryAware + BeanFactory 获取 BeanFactory* http://localhost:8080/application/context3* @return*/@GetMapping("application/context3")@SuppressWarnings("Duplicates")public Map<String, Object> applicationContext3() {PhoneController phoneController = BeanFactoryHelper.getBean(PhoneController.class);List<Map<String, Object>> mapList = phoneController.userList();Map<String, Object> dataMap = new HashMap<>(4);dataMap.put("mapList", mapList);return dataMap;}

src/main/java/com/wmx/jdbc_template_app/controller/PhoneController2.java · 汪少棠/jdbc_template_app - Gitee.com

ApplicationContextAware 获取 ApplicationContext

1、上面已经说过 ApplicationContext 接口是 BeanFactory 接口的扩展,功能得到了进一步增强,能使用的方法也更多。

2、BeanFactory 对应 BeanFactoryAware,ApplicationContext 对应 ApplicationContextAware ,使用起来完全同理。

/*** 1、spring 容器启动的时候会自动创建 ApplicationContextHelper 实例* 2、然后调用 setApplicationContext 回调方法自动注入 ApplicationContext* 3、有了 ApplicationContext 就可以 getBean 了*/
@Component
public class ApplicationContextHelper implements ApplicationContextAware {private static ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}/*** 根据名称获取容器中的对象实例* @param beanName :注入的实例必须已经存在容器中,否则抛异常:NoSuchBeanDefinitionException* @return*/public static Object getBean(String beanName) {return applicationContext.getBean(beanName);}/*** 根据 class 获取容器中的对象实例* @param requiredType :被注入的必须已经存在容器中,否则抛异常:NoSuchBeanDefinitionException* @param <T>* @return*/public static <T> T getBean(Class<T> requiredType) {return applicationContext.getBean(requiredType);}/*** 判断 spring 容器中是否包含指定名称的对象* @param beanName* @return*/public static boolean containsBean(String beanName) {return applicationContext.containsBean(beanName);}
}

src/main/java/com/wmx/jdbc_template_app/helper/ApplicationContextHelper.java · 汪少棠/jdbc_template_app - Gitee.com

   /*** ApplicationContextAware + ApplicationContext 获取 ApplicationContext* http://localhost:8080/application/context4* @return*/@GetMapping("application/context4")@SuppressWarnings("Duplicates")public Map<String, Object> applicationContext4() {PhoneController phoneController = ApplicationContextHelper.getBean(PhoneController.class);List<Map<String, Object>> mapList = phoneController.userList();Map<String, Object> dataMap = new HashMap<>(4);dataMap.put("mapList4", mapList);return dataMap;}

直接注入获取 IOC 容器

    /*** Spring 默认已经提供了 IOC 容器(BeanFactory & ApplicationContext) 的实例,可以直接注入使用。* 注意:从容器里面获取自己是没有的,但是可以直接注入使用。*/@Resourceprivate ApplicationContext applicationContext;@Resourceprivate BeanFactory beanFactory;

src/main/java/com/wmx/jdbc_template_app/controller/PhoneController2.java · 汪少棠/jdbc_template_app - Gitee.com

@Bean 添加实例时参数注入容器

/*** 应用配置类** @author wangMaoXiong* @version 1.0* @date 2022/4/21 21:28*/
@Configuration
public class AppConfig {/*** ========= 自定义 DataSourceTransactionManager 数据源事务管理器 =========* 1、如果程序中有多个数据源(javax.sql.DataSource),且没有设置首选 Bean (如@Primary标识),需要手动为 DataSourceTransactionManager 绑定需要的数据源* 2、采用配置类的形式,将其添加到容器中,这样程序中可以直接 @Autowired 或者 @Resource 注入使用。* 3、当然不在配置类中添加实例,直接在需要的地方 new DataSourceTransactionManager(DataSource dataSource) 也是可以的,同样放入目标数据源即可。* 4、使用 Qualifier 指定对应名称的数据源进行注入* <p>* <p>* ========= IOC容器(ApplicationContext)自动注入并使用 ApplicationContext =========* 1、@Bean 添加实例时,方法中的参数可以获取容器中的任意实例,比如数据源-DataSource,IOC容器自身-ApplicationContext* 2、@Bean 添加实例时,如果容器中同一类型存在多个实例,且没有标记优先级时,则需要使用 Qualifier 注解指定实例名称*/@Beanpublic DataSourceTransactionManager transactionManager(@Qualifier("dataSource") DataSource dataSource, ApplicationContext applicationContext) {// 程序一启动就会执行本方法,然后从容器中获取实例,查询数据库数据PhoneController phoneController1 = applicationContext.getBean(PhoneController.class);List<Map<String, Object>> mapList2 = phoneController1.userList();System.out.println(mapList2);DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);return transactionManager;}
}

src/main/java/com/wmx/jdbc_template_app/config/AppConfig.java · 汪少棠/jdbc_template_app - Gitee.com

启动类 Main 方法中获取 IOC 容器

1、启动 Spring Boot 项目时,main 方法中 SpringApplication.run() 方法的返回值 ConfigurableApplicationContext 就是 ApplicationContext 的子接口,所以可以把 run() 方法返回的ApplicationContext 对象保存下来,随时使用。

@SpringBootApplication
public class JdbcTemplateAppApplication {private static ApplicationContext applicationContext;public static void main(String[] args) {applicationContext = SpringApplication.run(JdbcTemplateAppApplication.class, args);String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();System.out.println("========服务启动成功,IOC容器中实例如下:");int count = 1;for (String beanDefinitionName : beanDefinitionNames) {System.out.println((count++) + ":实例名称:" + beanDefinitionName + ",类型:" + applicationContext.getBean(beanDefinitionName).getClass());}}
}

src/main/java/com/wmx/jdbc_template_app/JdbcTemplateAppApplication.java · 汪少棠/jdbc_template_app - Gitee.com

WebApplicationContextUtils 工具类获取IOC容器

1、Spring 提供了工具类- WebApplicationContextUtils,可用于获取 ApplicationContext 对象。

    /*** http://localhost:8080/application/context2* IOC 容器(BeanFactory & ApplicationContext) 实例通过内置 WebApplicationContextUtils 工具类获取* <p>* 获取 web 应用的根 WebApplicationContext(ApplicationContext的子接口)* * WebApplicationContext getRequiredWebApplicationContext(ServletContext sc)* * WebApplicationContext getWebApplicationContext(ServletContext sc)* * WebApplicationContext findWebApplicationContext(ServletContext sc)** @return*/@GetMapping("application/context2")public Map<String, Object> applicationContext2(HttpServletRequest request) {ApplicationContext webApplicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());WebApplicationContextUtils.findWebApplicationContext()PhoneController phoneController2 = (PhoneController) webApplicationContext.getBean("phoneController");List<Map<String, Object>> mapList2 = phoneController2.userList();Map<String, Object> dataMap = new HashMap<>(4);dataMap.put("mapList2", mapList2);return dataMap;}

src/main/java/com/wmx/jdbc_template_app/controller/PhoneController2.java · 汪少棠/jdbc_template_app - Gitee.com

Spring BeanFactory、ApplicationContext IOC 容器获取与使用相关推荐

  1. Spring简介与IOC容器

    一.Spring简介 开源:源码公开.免费试用: 简化:简化企业级开发. 解耦:耦合度降低.可插拔,便于后续维护更新升级拓展. 二.Sping核心模块 Spring 框架的这些模块可以满足一切企业级应 ...

  2. spring系列之IOC容器结构

    IOC容器结构 IOC(控制反转): 传统javaSE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象,而Ioc是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创 ...

  3. Spring技术内幕——Spring Framework的IOC容器实现(一)

    一.SpringIOC容器概述 IOC容器和依赖反转的模式 在面向对象的系统中,对象封装了数据和对数据的处理,对象的依赖关系常常体现在对数据和方法的依赖上.这些依赖关系可以通过把对象的依赖注入交给框架 ...

  4. Spring框架学习[IoC容器高级特性]

    1.通过前面4篇文章对Spring IoC容器的源码分析,我们已经基本上了解了Spring IoC容器对Bean定义资源的定位.读入和解析过程,同时也清楚了当用户通过getBean方法向IoC容器获取 ...

  5. 比Spring简单的IoC容器

    比Spring简单的IoC容器 Spring 虽然比起EJB轻量了许多,但是因为它需要兼容许多不同的类库,导致现在Spring还是相当的庞大的,动不动就上40MB的jar包, 而且想要理解Spring ...

  6. BeanFactory作为 IoC 容器示例

    /*** {@link BeanFactory} 作为 IoC 容器示例*/ public class BeanFactoryAsIoCContainerDemo {public static voi ...

  7. 最新最全面的Spring详解(一)——Spring概述与IOC容器

    前言 本文为 [Spring]Spring概述与IOC容器 相关知识,下边将对Spring概述,IOC容器(包括:IOC概述.配置元数据.容器实例化与使用.Bean的概述.依赖注入 Dependenc ...

  8. Spring核心技术之IOC容器(一):IOC容器与Bean简介

    最近开始研究Spring框架,今天学习Spring的核心内容IOC 与 Bean 1. Spring IOC 与 Bean 简介  Inversion of Control (IoC)即控制反转,也叫 ...

  9. Spring中的IOC容器原理

    什么是IOC: IOC(Inverse of Control)控制反转,将对象的创建权利反转给Spring框架. 它是面向对象编程中的一种设计原则,可以用来降低计算机代码之间的耦合度. IOC容器的底 ...

  10. Spring - 手把手分析 IoC 容器创建过程

    概述 这里我们以 Spring 5.2.8.RELEASE 版本为例,看一下 IoC 容器 的创建过程.同时我们使用 java-based 的方式实例化 IoC 容器,即使用 AnnotationCo ...

最新文章

  1. 马云启动“NASA”计划 为未来20年愿景研发核心科技
  2. 详细介绍如何在Eclipse中使用SVN
  3. 如何实现 asp.net core 安全优雅退出 ?
  4. 1064. 朋友数(20)
  5. 网络规划设计师论文考察要点
  6. Android系统----AS 3.1 支持的新版 D8,让你的编译更快、更小、更顺滑
  7. mongodb创建集合与php扩展
  8. 为什么用JS取不到cookie的值?解决方法如下!
  9. php定时任务引入文件,php解决crontab定时任务不能写入文件问题的方法分析
  10. java导出图片到excel_POI:将图片导出到Excel
  11. 列表的join方法,类方法formkeys,删除,集合,深浅拷贝赋值,冒泡排序
  12. java商城系统和php商城系统哪个好?
  13. html dom节点源码,HTML DOM HTML DOM 节点 - 闪电教程JSRUN
  14. 2022生物降解塑料展|广州可降解塑料展
  15. eclipse (氧气版)oxygen下载
  16. 【转】91个排名:中国知名个人站长及发家史
  17. python里d是什么意思?
  18. 【金融案例分析04】阿姆斯特丹股票交易所的历史(世界上最早的永续债券股票股票基金、郁金香泡沫、荷兰皇家壳牌集团、东印度公司)
  19. ESP在百度百科的阐述
  20. Nginx设置防爬虫策略

热门文章

  1. U-BOOT 编译过程
  2. 边相关扫描线填充算法
  3. 【数据分享】错颌畸形生长患者治疗数据集
  4. 拓端tecdat|R语言时间序列GARCH模型分析股市波动率
  5. 【大数据部落】用R语言挖掘Twitter数据
  6. Java学习(11-15天, 线性数据结构)
  7. 初中数学知识点总结_初中数学函数知识点总结
  8. DeepFake技术--辅助工具
  9. Python脚本编译为可跨平台、跨架构执行的字节码文件pyc方法
  10. 【Meachine Learning】lecture1 --吴恩达