SpringBoot获取bean的几种方式

news2024/11/25 2:32:15

目录

一、BeanFactory与ApplicationContext的区别

二、通过BeanFactory获取

三、通过BeanFactoryAware获取

四、启动获取ApplicationContext

五、通过继承ApplicationObjectSupport

六、通过继承WebApplicationObjectSupport

七、通过WebApplicationContextUtils

八、通过ApplicationContextAware

九、通过ContextLoader

十、通过BeanFactoryPostProcessor

十一、通过工具类获取


一、BeanFactory与ApplicationContext的区别

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

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

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

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

二、通过BeanFactory获取

通过BeanFactory来获取Bean。

基于xml配置文件:(不推荐使用)

BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));

User user = (User) beanFactory.getBean("user");

三、通过BeanFactoryAware获取

获取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容器通知。

示例如下:

@Component
public class BeanFactoryHelper implements BeanFactoryAware {

 private static BeanFactory beanFactory;

 /**
  * 重写 BeanFactoryAware 接口的方法
  * @param beanFactory :参数赋值给本地属性之后即可使用 BeanFactory
  * @throws BeansException BeansException
  */
 @Override
 public 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。

四、启动获取ApplicationContext

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

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

1.基于xml配置bean的形式,适用于比较古老的项目,已经很少使用了;

2.基于SpringBoot启动时获取ApplicationContext对象;

基于xml的形式实现:

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

基于SpringBoot启动实现:

@SpringBootApplication
public class ExampleApplication {

    public static void main(String[] args) {
        // 启动时,保存上下文,并保存为静态
        ConfigurableApplicationContext ac = SpringApplication.run(ExampleApplication.class, args);
        SpringContextUtil.setApplicationContext(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 setApplicationContext(ApplicationContext applicationContext){
        ac = applicationContext;
    }

}

五、通过继承ApplicationObjectSupport

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

具体实现代码:SpringContextUtil类需要实例化。

@Component
public class SpringContextUtil extends ApplicationObjectSupport {

 public <T> T getBean(Class<T> clazz) {
  ApplicationContext ac = getApplicationContext();
  if(ac == null){
   return null;
  }
  return ac.getBean(clazz);
 }
}

        ApplicationObjectSupport类图入下,我们看到它实现了ApplicationContextAware接口,在Spring容器初始化过程中回调方法setApplicationContext来完成ApplicationContext的赋值。

六、通过继承WebApplicationObjectSupport

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

具体实现代码如下:

@Component
public 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的一种方式,推荐使用。

具体实现代码如下:

@Component
public class SpringContextUtil3 implements ApplicationContextAware {

 private static ApplicationContext ac;

 @Override
 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  ac = applicationContext;
 }

 public static <T> T getBean(Class<T> clazz) {
  T bean = ac.getBean(clazz);
  return bean;
 }

}

九、通过ContextLoader

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

具体实现代码如下:

WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
wac.getBean(beanID);

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

十、通过BeanFactoryPostProcessor

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

@Component
public 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的子接口。

十一、通过工具类获取

  • RequestContextUtils.findWebApplicationContext(HttpServletRequest request)
  • WebApplicationContextUtils.getWebApplicationContext(ServletContext sc)

controller中获取:

public String test(HttpServletRequest request,HttpServletRequest response) {
    WebApplicationContext wc = RequestContextUtils.findWebApplicationContext(request);
    wc.getBean("beanName");

    WebApplicationContext wc2 = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
    wc2.getBean("beanName");
}

在service中或者其他后端服务中获取:

HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
WebApplicationContext wc = RequestContextUtils.findWebApplicationContext(request);
WebApplicationContext wc2 = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());

wc.getBean("beanName");
wc2.getBean("beanName");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2220249.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Chrome DevTools 三: Performance 性能面板扩展—— 性能优化

Performance 性能 &#xff08;一&#xff09;性能指标 首次内容绘制 (First Contentful Paint&#xff0c;FCP)&#xff1a; 任意内容在页面上完成渲染的时间 最大内容绘制 (Largest Contentful Paint&#xff0c;LCP)&#xff1a; 最大内容在页面上完成渲染的时间 第一字节…

创客项目秀|基于XIAO ESP32C3的本地个人助理Mr.M

作者&#xff1a;Matthew Yu 来自&#xff1a;Fab academy 在数字化时代的浪潮中&#xff0c;柴火创客空间作为创新与实践的摇篮&#xff0c;不仅为Fab Academy 2024的学员们提供了一个充满活力的学习和创作环境&#xff0c;更是将科技的力量与人文关怀深度融合。今天&#x…

Redis——事务

文章目录 Redis 事务Redis 的事务和 MySQL 事务的区别:事务操作MULTIEXECDISCARDWATCHUNWATCHwatch的实现原理 总结 Redis 事务 什么是事务 Redis 的事务和 MySQL 的事务 概念上是类似的. 都是把⼀系列操作绑定成⼀组. 让这⼀组能够批量执行 Redis 的事务和 MySQL 事务的区别:…

【Next.js 项目实战系列】07-分配 Issue 给用户

原文链接 CSDN 的排版/样式可能有问题&#xff0c;去我的博客查看原文系列吧&#xff0c;觉得有用的话&#xff0c;给我的库点个star&#xff0c;关注一下吧 上一篇【Next.js 项目实战系列】06-身份验证 分配 Issue 给用户 本节代码链接 Select Button​ # /app/issues/[i…

【Java】正则表达式详解

目录 引言 一、基本概念 1.1 元字符 1.2 预定义字符类 1.3 边界匹配符 1.4 数量标识符 1.5 捕获与非捕获分组 二、Java中的正则表达式支持 三、正则表达式的使用示例 3.1 匹配字符串 3.2 替换字符串 3.3 分割字符串 3.4 使用Pattern和Matcher 3.5 捕获组和后向…

【电商项目】1分布式基础篇

1 项目简介 1.2 项目架构图 1.2.1 项目微服务架构图 1.2.2 微服务划分图 2 分布式基础概念 3 Linux系统环境搭建 查看网络IP和网关 linux网络环境配置 补充P123&#xff08;修改linux网络设置&开启root密码访问&#xff09; 设置主机名和hosts映射 主机名解析过程分析&…

金九银十互联网大厂Java高频面试题(2024最新含答案)

2024 年的互联网行业竞争越来越严峻&#xff0c;面试也是越来越难&#xff0c;一直以来我都想整理一套完美的面试宝典&#xff0c;奈何难抽出时间&#xff0c;这套 1200道的 Java 面试手册我整理了整整 1 个月&#xff0c;上传到 Git 上目前 star 数达到了 30K 这套互联网 Jav…

冲击美团!已成功 OC

这是一位训练营学员的美团面经&#xff0c;目前已经 OC 。 在此之前他已经拿到了不少公司的offer&#xff0c;但是都达不到他的预期&#xff0c;美团给的待遇就非常不错&#xff0c;大厂不愧是大厂&#xff0c;就是不知道工作强度如何。 他经历了一共三场面试&#xff0c;一面…

实现省略号查看详情样式

1.期望实现效果 2.目前实现效果 3.实现代码 1.wxml<view class"desc-text"><view class"show-more">查看详情 >></view><!-- <rich-text nodes"{{富文本接口数据内容 }}"></rich-text> --><text&…

python反爬

1.无限debug无法f12 关闭掉 Deactivate Breakpoints

【闲谈程序设计例三则:抛弃传统单步进初级阶段,用推导归纳出来的规律写代码,进入进阶阶段,人类自性的高级活动。】2024-10-21

闲谈程序设计三则&#xff1a;抛弃传统单步进&#xff0c;用推导归纳出来的规律写代码。 本论坛常见新学提问都是一些入门级别的问题&#xff0c;近来AI活跃抢答&#xff0c;然而&#xff0c;对于有些问题AI可以说是答非所问&#xff0c;令人哭笑不得&#xff0c;而AI能回答的…

MacOS安装BurpSuite

文章目录 一、下载地址二、下载注册机三、安装教程四、启动burpsuit五、免责声明 一、下载地址 https://portswigger-cdn.net/burp/releases/download?productpro&version2024.7.1&typeMacOsx二、下载注册机 https://github.com/NepoloHebo/BurpSuite-BurpLoaderKey…

B站协议登录到实现各种功能完整代码(专栏总结)

B站协议登录、点赞、收藏、转发实现及代码 关注、动态转发实现动态抽奖实现及代码 直播预约抽奖实现及代码 本文为本专栏的总结文章 一、扫码登录 请求获取二维码包&#xff0c;得到二维码链接和qrcode_key参数之后&#xff0c;利用qrcode_key循环GET请求登录状态包即可&#x…

【word】页眉横线无法取消

小伙伴们日常想在页眉里加横线&#xff0c;直接双击页眉&#xff0c;然后在页眉横线里选择自己喜欢的横线样式就可以了。 但今天我遇到的这个比较奇特&#xff0c;有些页有这个横线&#xff0c;有些页没有&#xff0c;就很奇怪。 最后排查完&#xff0c;发现是只有标题2的页…

WPF入门_02依赖属性

1、依赖属性主要有以下三个优点 1)依赖属性加入了属性变化通知、限制、验证等功能。这样可以使我们更方便地实现应用,同时大大减少了代码量 2)节约内存:在WinForm中,每个UI控件的属性都赋予了初始值,这样每个相同的控件在内存中都会保存一份初始值。而WPF依赖属性很好地…

《向量数据库指南》揭秘:Mlivus Cloud如何赋能GraphRAG应用

嘿,各位向量数据库和AI领域的探索者们,我是你们的老朋友,大禹智库的向量数据库高级研究员王帅旭,也是《向量数据库指南》的作者。今天,咱们来聊聊一个既前沿又实用的话题——检索增强生成(Retrieval Augmented Generation,简称RAG)及其面临的挑战,特别是如何用Mlivus …

前端/node.js锁定依赖版本、锁定依赖的依赖的版本

一、知识前提 version&#xff1a;必须依赖某个具体的版本。如&#xff1a;vue的3.2.0&#xff0c;表示必须安装3.2.0版本。>version&#xff1a;必须大于某个版本。>version&#xff1a;大于或等于某个版本。<version&#xff1a;必须小于某个版本。<version&…

多线程——单例模式

目录 前言 一、设计模式 二、饿汉模式 三、懒汉模式 1.单线程版 2.多线程版 结尾 前言 前面的几篇文章中介绍了多线程编程的基础知识&#xff0c;在本篇文章开始&#xff0c;就会利用前面的多线程编程知识来编写一些代码案例&#xff0c;从而使大家可以更好的理解运用多…

扩散模型对抗蒸馏:ADD 和 Latent-ADD

扩散模型对抗蒸馏&#xff1a;ADD 和 Latent-ADD ADD&#xff08;Adversarial Diffusion Distillation&#xff09;和 Latent-ADD 是 StabilityAI 公司提出的一系列针对 Stable Diffusion 的扩散模型对抗蒸馏方法&#xff0c;通过对抗训练和蒸馏训练来提高扩散模型的采样速度&…

python基于图片内容识别的微信自动发送信息(对其中逻辑修改一些可以改为自动化回复)

1.内容基于python日常生活问题帮助 2.主要框架 import time from datetime import datetimeimport pyperclip import win32api import win32con import os import refrom Image_Content_Text_Recognition import ICTR from screenshot import img 上面是逻辑部分主要框架 i…