位置: IT常识 - 正文

Spring获取Bean的9种方式(spring获取bean的完全限定类名)

编辑:rootadmin
Spring获取Bean的9种方式 前言

推荐整理分享Spring获取Bean的9种方式(spring获取bean的完全限定类名),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:spring获取bean的过程,spring获取bean的name,spring获取bean的工具类,spring获取bean的名字,spring获取bean的几种方式,spring获取bean的注解,spring获取bean的完全限定类名,spring获取bean的方式,内容如对您有帮助,希望把文章链接给更多的朋友!

随着SpringBoot的普及,Spring的使用也越来越广,在某些场景下,我们无法通过注解或配置的形式直接获取到某个Bean。比如,在某一些工具类、设计模式实现中需要使用到Spring容器管理的Bean,此时就需要直接获取到对应的Bean。

本文为大家整理汇总了常见的获取Bean的方式,并提供一些优劣分析,方便大家在使用到时有更好的选择。同时,也会为大家适当的普及和拓展一些相关知识。

Spring的IoC容器

在Spring中,Bean的实例化、定位、配置应用程序中的对象及建立对象间的依赖关系,都是在IoC容器中进行的。因此,要在Spring中获取Bean,本质上就是从IoC容器当中获取Bean。

在Spring中,BeanFactory是IoC容器的实际代表者,该接口提供了IoC容器最基本功能。同时,Spring还提供了另外一种类型的容器:ApplicationContext容器。

ApplicationContext容器包括BeanFactory容器的所有功能(BeanFactory的子接口),提供了更多面向应用的功能,它提供了国际化支持和框架事件体系,更易于创建实际应用。

一般情况,我们称BeanFactory为IoC容器,称ApplicationContext为应用上下文。但有时为了方便,也将ApplicationContext称为Spring容器。

通常不建议使用BeanFactory,但BeanFactory 仍然可以用于轻量级的应用程序,如移动设备或基于applet的应用程序,其中它的数据量和速度是显著。

BeanFactory与ApplicationContext的区别

BeanFactory是Spring框架的基础设施,面向Spring本身。ApplicationContext则面向使用Spring框架的开发者,几乎所有的应用场合都可以直接使用ApplicationContext,而非底层的BeanFactory。

另外,ApplicationContext的初始化和BeanFactory有一个重大的区别:

BeanFactory在初始化容器时,并未实例化Bean,直到第一次访问某个Bean时才实例目标Bean。这样,我们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常。

而ApplicationContext则在初始化应用上下文时就实例化所有单实例的Bean,相对应的,ApplicationContext的初始化时间会比BeanFactory长一些。

了解了上述的基本理论知识之后,我们就可以尝试从IoC容器当中获取Bean对象了。

方式一:通过BeanFactory获取

通过BeanFactory来获取Bean。基于xml配置文件的时代,可以通过如下方式获得BeanFactory,再通过BeanFactory来获得对应的Bean。

BeanFactorybeanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));UserInfo userInfo = (UserInfo) beanFactory.getBean("userInfo");复制代码

有一定编程年龄的程序员,应该对此还有一些印象。这种写法估计也只会出现在古老的项目当中。鉴于xml形式配置文件已经被基于注解形式所替代,同时XmlBeanFactory也被标注为废弃。此种方式不推荐使用。

其实,不推荐的理由还有一个,在上面已经提到,尽量不要使用BeanFactory,而应该使用ApplicationContext。

方式二:通过BeanFactoryAware获取

在上面的方式中,XmlBeanFactory已经被废弃,但可以通过其他方式来获得BeanFactory,然后再从BeanFactory中获得指定的Bean。获取BeanFactory实例最简单的方式就是实现BeanFactoryAware接口。

BeanFactoryAware接口源码:

public interface BeanFactoryAware extends Aware {​/*** 初始化回调方法,Spring会自动将BeanFactory注入进去,接收之后即可使用BeanFactory*/void setBeanFactory(BeanFactory beanFactory) throws BeansException;}复制代码

BeanFactoryAware属于org.springframework.beans.factory.Aware根标记接口,使用setter注入来在应用程序上下文启动期间获取对象。Aware接口是回调,监听器和观察者设计模式的混合,它表示Bean有资格通过回调方式被Spring容器通知。

这里提供一个完整的工具类:

@Componentpublic class BeanFactoryHelper implements BeanFactoryAware {​private static BeanFactory beanFactory;​/*** 重写 BeanFactoryAware 接口的方法* @param beanFactory :参数赋值给本地属性之后即可使用 BeanFactory* @throws BeansException BeansException*/@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {BeanFactoryHelper.beanFactory = beanFactory;}/*** 根据名称获取容器中的对象实例* @param beanName :注入的实例必须已经存在容器中,否则抛异常:NoSuchBeanDefinitionException* @return Object*/public static Object getBean(String beanName) {return beanFactory.getBean(beanName);}/*** 根据 class 获取容器中的对象实例* @param requiredType :被注入的必须已经存在容器中,否则抛异常:NoSuchBeanDefinitionException* @param <T> Class* @return 对象*/public static <T> T getBean(Class<T> requiredType) {return beanFactory.getBean(requiredType);}/*** 判断 spring 容器中是否包含指定名称的对象* @param beanName bean名称* @return 是否存在*/public static boolean containsBean(String beanName) {return beanFactory.containsBean(beanName);}//其它需求皆可参考 BeanFactory 接口和它的实现类}复制代码

在上述工具类中,便是基于BeanFactoryAware的特性,获得了BeanFactory,然后再通过BeanFactory来获得指定的Bean。

该方案满足了获取Bean的基本需求,但同时具有使用BeanFactory的缺点。根据前文介绍的BeanFactory特性,可酌情使用。

上面提供了两种基于BeanFactory容器获得Bean的方式,下面则通过ApplicationContext来获取容器中的Bean,不同的是获取ApplicationContext的方式的区别。

方式三:启动获取ApplicationContextSpring获取Bean的9种方式(spring获取bean的完全限定类名)

在项目启动时先获取ApplicationContext对象,然后将其存储在一个地方,以便后续用到时进行使用。

这里提供两种场景的获取:

基于xml配置bean的形式,适用于比较古老的项目,已经很少使用了;基于SpringBoot启动时获取ApplicationContext对象;

基于xml的形式实现:

// 其中applicationContext.xml 为配置容器的xml,不过现在一般很少使用了ApplicationContextac = new FileSystemXmlApplicationContext("applicationContext.xml");复制代码

这里等于直接初始化容器,并且获得容器的引用。这种方式适用于采用Spring框架的独立应用程序,需要程序通过配置文件手工初始化Spring的情况。目前大多数Spring项目已经不再采用xml配置,很少使用了。

基于SpringBoot启动实现:

@SpringBootApplicationpublic class ExampleApplication {​  public static void main(String[] args) {      // 启动时,保存上下文,并保存为静态      ConfigurableApplicationContext ac = SpringApplication.run(ExampleApplication.class, args);      SpringContextUtil.setAc(ac);  }}复制代码

对应的SpringContextUtil类如下:

public class SpringContextUtil1 {​  private static ApplicationContext ac;​  public static <T> T getBean(String beanName, Class<T> clazz) {      T bean = ac.getBean(beanName, clazz);      return bean;  }​  public static void setAc(ApplicationContext applicationContext){      ac = applicationContext;  }}复制代码

两种方式都是在启动Spring项目时,直接获取到ApplicationContext的引用,然后将其存储到工具类当中。在使用时,则从工具类中获取ApplicationContext容器,进而从中获得Bean对象。

方式四:通过继承ApplicationObjectSupport

此种方式依旧是先获得ApplicationContext容器,然后从中获取Bean对象,只不过是基于继承ApplicationObjectSupport类实现的。

具体实现代码:

@Componentpublic class SpringContextUtil extends ApplicationObjectSupport {public <T> T getBean(Class<T> clazz) {ApplicationContext ac = getApplicationContext();if(ac == null){return null;}return ac.getBean(clazz);}}复制代码

注意,这里的SpringContextUtil类需要实例化。

方式五:通过继承WebApplicationObjectSupport

WebApplicationObjectSupport是ApplicationObjectSupport的一个实现类,提供了Web相关的支持。实现原理与ApplicationObjectSupport一样。

具体实现代码如下:

@Componentpublic class SpringContextUtil extends WebApplicationObjectSupport {public <T> T getBean(Class<T> clazz) {ApplicationContext ac = getApplicationContext();if(ac == null){return null;}return ac.getBean(clazz);}}复制代码

对照基于ApplicationObjectSupport的实现,除了继承对象不同外,没有其他区别,都是基于getApplicationContext方法来获取。

方式六:通过WebApplicationContextUtils

Spring提供了工具类WebApplicationContextUtils,通过该类可获取WebApplicationContext对象。

具体实现代码如下:

public class SpringContextUtil2 {public static <T> T getBean(ServletContext request, String name, Class<T> clazz){WebApplicationContext webApplicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(request);// 或者WebApplicationContext webApplicationContext1 = WebApplicationContextUtils.getWebApplicationContext(request);//       webApplicationContext1.getBean(name, clazz)T bean = webApplicationContext.getBean(name, clazz);return bean;}}复制代码

这个方法很常见于SpringMVC构建的Web项目中,适用于Web项目的B/S结构。

方式七:通过ApplicationContextAware

通过实现ApplicationContextAware接口,在Spring容器启动时将ApplicationContext注入进去,从而获取ApplicationContext对象,这种方法也是常见的获取Bean的一种方式,推荐使用。

具体实现代码如下:

@Componentpublic class SpringContextUtil3 implements ApplicationContextAware {​private static ApplicationContext ac;​@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {ac = applicationContext;}​public static <T> T getBean(Class<T> clazz) {T bean = ac.getBean(clazz);return bean;}​}复制代码

这种方式与前面通过BeanFactoryAware获得BeanFactory的思路一致。

方式八:通过ContextLoader

使用ContextLoader提供的getCurrentWebApplicationContext方法,也是常用的获取WebApplicationContext的一种方法。

具体实现代码如下:

WebApplicationContextwac = ContextLoader.getCurrentWebApplicationContext();wac.getBean(beanID);复制代码

该方法常见于SpringMVC实现的Web项目中。该方式是一种不依赖于Servlet,不需要注入的方式。但是需要注意一点,在服务器启动时和Spring容器初始化时,不能通过该方法获取Spring容器。

方式九:通过BeanFactoryPostProcessor

Spring工具类,方便在非Spring管理环境中获取Bean。

@Componentpublic final class SpringUtils implements BeanFactoryPostProcessor{     /** Spring应用上下文环境 */  private static ConfigurableListableBeanFactory beanFactory;​  @Override  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException{      SpringUtilsS.beanFactory = beanFactory;  }​  /**    * 获取对象    *    * @param name    * @return Object 一个以所给名字注册的bean的实例    * @throws BeansException    *    */  @SuppressWarnings("unchecked")  public static <T> T getBean(String name) throws BeansException{      return (T) beanFactory.getBean(name);  }​  /**    * 获取类型为requiredType的对象    *    * @param clz    * @return    * @throws BeansException    *    */  public static <T> T getBean(Class<T> clz) throws BeansException{      T result = (T) beanFactory.getBean(clz);      return result;  }​  /**    * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true    *    * @param name    * @return boolean    */  public static boolean containsBean(String name){      return beanFactory.containsBean(name);  }​  /**    * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)    *    * @param name    * @return boolean    * @throws NoSuchBeanDefinitionException    *    */  public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException{      return beanFactory.isSingleton(name);  }​  /**    * @param name    * @return Class 注册对象的类型    * @throws NoSuchBeanDefinitionException    *    */  public static Class<?> getType(String name) throws NoSuchBeanDefinitionException{      return beanFactory.getType(name);  }​  /**    * 如果给定的bean名字在bean定义中有别名,则返回这些别名    *    * @param name    * @return    * @throws NoSuchBeanDefinitionException    *    */  public static String[] getAliases(String name) throws NoSuchBeanDefinitionException{      return beanFactory.getAliases(name);  }​  /**    * 获取aop代理对象    *    * @param invoker    * @return    */  @SuppressWarnings("unchecked")  public static <T> T getAopProxy(T invoker){      return (T) AopContext.currentProxy();  }}复制代码

其中ConfigurableListableBeanFactory接口,也属于BeanFactory的子接口。

小结

在本文中介绍了9种从Spring容器中获取Bean的方法,虽然每种方式实现各有不同,但从本质上来讲,无非就是通过BeanFactory或ApplicationContext获取Bean,只不过获取BeanFactory或ApplicationContext容器的方式不同而已。

那么,你是否意识到,学习一项技术或一个实现方式,只要把握住它的根本,无论形式如何变化,都万变不离其宗。而这里“宗”就是IoC容器。

来源:https://juejin.cn/post/7187939675707801637

本文链接地址:https://www.jiuchutong.com/zhishi/299535.html 转载请保留说明!

上一篇:HTML购物车示例(勾选、删除、添加和结算功能)(购物车html模板)

下一篇:人工智能大模型多场景应用原理解析(人工智能大模型体验报告3.0)

  • 苹果手机和苹果手表怎么配对(苹果手机和苹果电脑怎么投屏)

    苹果手机和苹果手表怎么配对(苹果手机和苹果电脑怎么投屏)

  • qq怎么设置好友互动标识(qq怎么设置好友生日提醒)

    qq怎么设置好友互动标识(qq怎么设置好友生日提醒)

  • 打电话提示无法访问移动网络(打电话提示无法接听电话是什么意思)

    打电话提示无法访问移动网络(打电话提示无法接听电话是什么意思)

  • 微信退出后重新登录聊天记录(微信退出后重新登录聊天记录怎么恢复)

    微信退出后重新登录聊天记录(微信退出后重新登录聊天记录怎么恢复)

  • 打招呼频繁多久才能自动解封(打招呼过于频繁什么时候可以加人)

    打招呼频繁多久才能自动解封(打招呼过于频繁什么时候可以加人)

  • oppo出现hd1是什么意思(oppo手机出现hd1)

    oppo出现hd1是什么意思(oppo手机出现hd1)

  • ntfs.sys损坏无法开机(ntfs.sys损坏无法开机win10)

    ntfs.sys损坏无法开机(ntfs.sys损坏无法开机win10)

  • 帮朋友解封微信为什么不符合要求(帮朋友解封微信朋友圈有风险吗)

    帮朋友解封微信为什么不符合要求(帮朋友解封微信朋友圈有风险吗)

  • 淘宝经常购物互动是什么意思(淘宝经常购物互动怎么删除)

    淘宝经常购物互动是什么意思(淘宝经常购物互动怎么删除)

  • 无线网红灯闪怎么回事(无线网红色灯亮怎么回事)

    无线网红灯闪怎么回事(无线网红色灯亮怎么回事)

  • qq启动失败怎么修复(qq启动失败怎么重新启动)

    qq启动失败怎么修复(qq启动失败怎么重新启动)

  • 饱和度和自然饱和度的区别(饱和度和自然饱度各调多少合适)

    饱和度和自然饱和度的区别(饱和度和自然饱度各调多少合适)

  • 安卓手机设置个人热点(安卓的设置在哪里)

    安卓手机设置个人热点(安卓的设置在哪里)

  • 苹果cha是什么意思(苹果ch什么意思)

    苹果cha是什么意思(苹果ch什么意思)

  • 苹果7p支持几w充电(苹果7p支持多大w的充电器)

    苹果7p支持几w充电(苹果7p支持多大w的充电器)

  • 微信实名认证不了怎么办(微信实名认证不添加银行卡可以吗)

    微信实名认证不了怎么办(微信实名认证不添加银行卡可以吗)

  • qq音乐怎么收藏自己的歌单(QQ音乐怎么收藏MV)

    qq音乐怎么收藏自己的歌单(QQ音乐怎么收藏MV)

  • iphonex怎么设置软件锁(iphoneX怎么设置铃声自定义)

    iphonex怎么设置软件锁(iphoneX怎么设置铃声自定义)

  • 华为删除的录音怎么恢复(华为删除的录音文件)

    华为删除的录音怎么恢复(华为删除的录音文件)

  • 腾讯地图如何标注地点(腾讯地图如何标注自己店铺位置要钱吗)

    腾讯地图如何标注地点(腾讯地图如何标注自己店铺位置要钱吗)

  • static变量的作用(static变量存储在什么区域)

    static变量的作用(static变量存储在什么区域)

  • 佳能200d怎么对焦(佳能200d使用教程)

    佳能200d怎么对焦(佳能200d使用教程)

  • ios13快捷指令怎么用(快捷指令ios13 使用教程)

    ios13快捷指令怎么用(快捷指令ios13 使用教程)

  • 华为畅享9plus充电要多久(华为畅享9plus充电接口类型)

    华为畅享9plus充电要多久(华为畅享9plus充电接口类型)

  • 华为mate20声音小怎么调(荣耀magic5声音小怎么办)

    华为mate20声音小怎么调(荣耀magic5声音小怎么办)

  • 钉钉如何自动打卡(钉钉如何自动打卡无需打开程序)

    钉钉如何自动打卡(钉钉如何自动打卡无需打开程序)

  • 企业所得税年报申报时间
  • 土地价款抵扣增值税怎么做账
  • 税务师厉害吗
  • 公司基本户里的钱有利息吗
  • 福利费进项税转出的会计分录
  • 关联交易所得税规定
  • 原材料入库是付款凭证吗
  • 土地增值税预缴政策
  • 企业收到免税发票后怎么开票
  • 民非企业缴纳社保会计分录
  • 房地产未确认收入情况说明
  • 普通发票打歪了可以用吗
  • 耕地占用税和土地使用税的区别
  • 实际销售金额是开票金额吗
  • 劳务派遣企业差额扣除占比过高怎么办
  • 固定资产评估增值
  • 净资产属于政府预算会计要素吗
  • 年中建账损益类科目怎么录
  • 苹果电脑开机声音怎么关
  • 苹果iphone6s plus打电话没有人名
  • 银行与银行之间转账会计摘要
  • 如何安装u盘的系统
  • 物业专项维修资金可以退还吗
  • php call方法
  • window清除临时存储文件夹
  • 文件pages
  • 企业向银行申请办理非原路的服务贸易退汇,银行应当
  • 借款成坏账了怎么处理
  • 员工食堂餐费可以税前扣除吗
  • 不符合win11硬件要求安装会怎么样
  • 便秘怎么办 女性
  • php __destruct
  • 为什么增值税最后有余额附加税没有
  • 马尔堡酒庄
  • Symfony2 session用法实例分析
  • 退回的企业所得税怎么做账
  • 公司房产处置
  • php支付功能
  • javaweb简单项目案例
  • 车辆购置税发票在哪里打印
  • 银行存款利息收入会计分录怎么写
  • 归还股东投资款
  • 将织梦dedecms转换到wordpress
  • db2入门
  • sql查询使用临时表
  • 结转上年
  • 淘宝上买资料可以退吗
  • 库存股属于什么账户
  • 个体户没有税务登记怎么开发票
  • 计划成本法有什么差异
  • 母公司无偿借款给子公司
  • 税务机关如何对个人股东股权财务报表审核
  • 补付预付账款账务处理分录
  • 付当月房租怎么做分录
  • 银行存款支付比例规定
  • 上年度会计凭证怎么填
  • 残疾人就业保障金
  • 自然人股权转让如何缴纳个人所得税
  • sqlserver (parse name)字符串截取的方法
  • mysql替换命令
  • Windows Server 2003网络负载均衡如何实现
  • Ubuntu14.4下Sublime Text 3无法输入中文解决方法
  • assoc .exe=exefile是什么
  • 用U盘安装系统重启后进不去
  • windows中创建的任务计划可以多久执行一次任务?
  • cocos2dx用什么ide
  • Android游戏开发案例教程小小弹球
  • html+css网页布局
  • 英语中our和my的区别
  • shell脚本一百例
  • css教程大全
  • pcs可以使用什么在任何地方以各种速率与网络保持联络
  • unity3d脚本怎么用
  • js验证正整数
  • activity的跳转
  • python 如何访问数据库
  • 北京中石化开增票各区网点
  • 出租车票据国税怎么开
  • 烟叶税比例
  • 税务宣传标语2021
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设