SpringBoot获取bean的几种方式

server/2024/10/20 21:08:04/

目录

一、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配置文件:(不推荐使用)

java">BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));User user = (User) beanFactory.getBean("user");

三、通过BeanFactoryAware获取

获取BeanFactory实例最简单的方式就是实现BeanFactoryAware接口。

BeanFactoryAware接口源码:

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

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

示例如下:

java">@Component
public 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。

四、启动获取ApplicationContext

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

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

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

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

基于xml的形式实现:

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

基于SpringBoot启动实现:

java">@SpringBootApplication
public class ExampleApplication {public static void main(String[] args) {// 启动时,保存上下文,并保存为静态ConfigurableApplicationContext ac = SpringApplication.run(ExampleApplication.class, args);SpringContextUtil.setApplicationContext(ac);}
}

对应的SpringContextUtil类如下:

java">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类需要实例化。

java">@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一样。

具体实现代码如下:

java">@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对象。

具体实现代码如下:

java">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的一种方式,推荐使用。

具体实现代码如下:

java">@Component
public 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;}}

九、通过ContextLoader

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

具体实现代码如下:

java">WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
wac.getBean(beanID);

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

十、通过BeanFactoryPostProcessor

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

java">@Component
public final class SpringUtils implements BeanFactoryPostProcessor{/** Spring应用上下文环境 */private static ConfigurableListableBeanFactory beanFactory;@Overridepublic 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中获取:

java">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中或者其他后端服务中获取:

java">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.ppmy.cn/server/133449.html

相关文章

贪心day3

文章目录 前言幸福值最大化的选择方案从一个范围内选择最多整数 I摧毁小行星重排数组以得到最大前缀分数三角形的最大周长 前言 &#x1f4ab;你好&#xff0c;我是辰chen&#xff0c;本文旨在准备考研复试或就业 &#x1f4ab;文章题目大多来自于 leetcode&#xff0c;当然也可…

C++面试速通宝典——28

527. 讲一下平衡二叉搜索树&#xff0c;删除非叶子节点后如何调整&#xff1f; 平衡二叉搜索树&#xff08;比如AVL树或红黑树&#xff09;是一种在每次插入和删除后能够自平衡的二叉搜索树&#xff0c;以保证树的高度尽可能地低&#xff0c;从而保证操作的性能。 删除非叶子…

Java基础:面向对象编程8

1 Java 注解 1.1 概念 定义&#xff1a;注解&#xff08;Annotation&#xff09;是在 Java 1.5 时引入的概念&#xff0c;同 class 和 interface 一样&#xff0c;属于一种类型。作用&#xff1a;注解提供了一系列数据用来装饰程序代码&#xff08;类、方法、字段等&#xff…

基于MATLAB的交通标志的识别

一、背景 随着交通技术的日益完善和交通工具的多样化发展&#xff0c;交通安全成为当前最热门的问 题&#xff0c;道路交通关系着人们的生命以及财产安全。 交通标志的识别是保证交通安全的一个重要环节。交通标识包含丰富的道路交通信 息&#xff0c;为驾驶员提供警示、指示…

C++ 11 的 codecvt 与编码转换

1 编码与乱码 乱码产生的主要原因是编码与字符集不匹配&#xff0c;这种不匹配时怎么造成的呢&#xff1f;首先要来了解一下编码和字符集的关系。 1.1 编码与字符集 由于标准的英文 ASCII 已经成了全球标准&#xff0c;每台电脑的 BIOS 里存着一份标准 ASCII 表&#xff08;…

基于K8S的StatefulSet部署mysql主从

StatefulSet特性 StatefulSet的网络状态 拓扑状态&#xff1a;应用的多个实例必须按照某种顺序启动&#xff0c;并且必须成组存在&#xff0c;例如一个应用中必须存在一 个A Pod和两个B Pod&#xff0c;且A Pod必须先于B Pod启动的场景 存储状态&#xff1a;应用存在多个实例…

python——pyecharts数据可视化堆叠面积图

堆叠面积图具有以下几个重要作用&#xff1a; 一、展示总量与分量关系 堆叠面积图可以清晰地展示多个数据系列的总量以及各个分量在总量中所占的比例。通过不同颜色或阴影的区域&#xff0c;你可以直观地看出每个数据系列对整体的贡献程度。例如&#xff0c;在分析公司不同业…

LLAMA2入门(一)-----预训练

Llama 2 是预训练和微调的LLM系列&#xff0c;Llama 2 和 Llama 2-Chat 模型的参数规模达到 70B。Llama 2-Chat 模型专门为对话场景进行了优化。 这是一个系列的文章&#xff0c;会分别从LLAMA2的预训练&#xff0c;微调&#xff0c;安全性等方面进行讲解。 1.数据来源 数据…