需求:使用 @autowired注入一些对象,但发现不可以直接使用@Autowired,因为方法是static的,要使用该方法当前对象也必须是static,正常情况下@Autowired无法注入静态的bean,于是发现项目中用到了springContextHolder,通过使用

private T t= SpringContextHolder.getBean(T.class);

或者我们在刚开始学习的时候,会使用如下这种方式来获取 Bean。但是这样就会存在一个问题,因为它需要重新装载 spring-core.xml 文件,并实例化上下文bean,如果有些线程配置类也是在这个配置文件中,那么会造成做相同工作的的线程会被启两次。一次是 web容器初始化时启动,另一次是上述代码显示的实例化了一次。这样就产生了冗余。下面就来说说解决方案。

ApplicationContext appContext = new ClassPathXmlApplicationContext("spring-core.xml");
T t = (T)appContext.getBean("t");

一、SpringContextHolder 工具类


自定义 SpringContextHolder 工具类,全网统一模板。需要将该类注入到 Spring IOC 中。因此路径很重要。

 1 package com.zzx.utils;
2
3 import lombok.extern.slf4j.Slf4j;
4 import org.springframework.beans.BeansException;
5 import org.springframework.beans.factory.DisposableBean;
6 import org.springframework.context.ApplicationContext;
7 import org.springframework.context.ApplicationContextAware;
8
9 /**
10 * @author
11 * @date
12 */
13 @Component
14 @Slf4j
15 public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
16
17 private static ApplicationContext applicationContext = null;
18
19 /**
20 * 取得存储在静态变量中的ApplicationContext.
21 */
22 public static ApplicationContext getApplicationContext() {
23 assertContextInjected();
24 return applicationContext;
25 }
26
27 /**
28 * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
29 */
30 public static <T> T getBean(String name) {
31 assertContextInjected();
32 return (T) applicationContext.getBean(name);
33 }
34
35 /**
36 * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
37 */
38 public static <T> T getBean(Class<T> requiredType) {
39 assertContextInjected();
40 return applicationContext.getBean(requiredType);
41 }
42
43 /**
44 * 检查ApplicationContext不为空.
45 */
46 private static void assertContextInjected() {
47 if (applicationContext == null) {
48 throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" +
49 ".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder.");
50 }
51 }
52
53 /**
54 * 清除SpringContextHolder中的ApplicationContext为Null.
55 */
56 public static void clearHolder() {
57 log.debug("清除SpringContextHolder中的ApplicationContext:"
58 + applicationContext);
59 applicationContext = null;
60 }
61
62 @Override
63 public void destroy() throws Exception {
64 SpringContextHolder.clearHolder();
65 }
66
67 @Override
68 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
69 if (SpringContextHolder.applicationContext != null) {
70 log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext);
71 }
72 SpringContextHolder.applicationContext = applicationContext;
73 }
74 }

二、ApplicationContextAware接口


Spring容器初始化的时候会检测容器中的所有Bean,如果发现某个Bean实现了ApplicationContextAware接口,Spring容器会在创建该Bean之后,自动调用该 Bean的 setApplicationContextAware()方法,调用该方法时,会将容器本身作为参数传给该方法,该方法将 Spring传入的参数(容器本身)赋给该类对象的 applicationContext实例变量,因此接下来可以通过该applicationContext实例变量来访问容器本身。

使用 ApplicationContextAware 定义 SpringContextHolder 类的更多相关文章

  1. SpringContextHolder类

    1.通常使用SpringContextHolder类获取bean实例: 解决: 如果要在静态方法中调用某一bean的方法,那么该bean必须声明为static的,但正常情况下@Autowired无法注 ...

  2. 类的继承和多态性-编写Java应用程序,定义Animal类,此类中有动物的属性:名称 name,腿的数量legs,统计动物的数量 count;方法:设置动物腿数量的方法 void setLegs(),获得腿数量的方法 getLegs(),设置动物名称的方法 setKind(),获得动物名称的方法 getKind(),获得动物数量的方法 getCount()。定义Fish类,是Animal类的子类,

    编写Java应用程序,定义Animal类,此类中有动物的属性:名称 name,腿的数量legs,统计动物的数量 count;方法:设置动物腿数量的方法 void setLegs(),获得腿数量的方法 ...

  3. KVC在定义Model类中的妙用

    @我们应用程序使用MVC架构的话,对于处理数据类,我们会单独的定义Model类,在里面为要展示的属性进行初始化赋值,一般採用的方法是通过定义相应的属性,挨个赋值.如今我要介绍的就是通过KVC,key- ...

  4. 定义Java类的数组的问题

    定义了一个类: class Student{ private int Id; public int getId() { return Id; } public void setId(int id) { ...

  5. Java TreeSet集合排序 && 定义一个类实现Comparator接口,覆盖compare方法 && 按照字符串长度排序

    package TreeSetTest; import java.util.Iterator; import java.util.TreeSet; import javax.management.Ru ...

  6. applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder.

    我用的jeesite框架,在使用定时任务时,出现一些问题,,1.在windows上项目可以在tomcat下,运行2.在linux下项目在tomcatgh下,却出现问题: 15-Dec-2017 15: ...

  7. JavaScript数据结构与算法(八) 集合(ECMAScript 6中定义的类似的Set类)

    TypeScript方式实现源码 // 特性: // 1. 集合是由一组无序且唯一(即不能重复)的项组成的.这个数据结构使用了与有限集合相同的数学概念,但应用在计算机科学的数据结构中. // 2. 也 ...

  8. JAVA 类的定义(定义一个类,来模拟“学生”)

    package Code413;/*定义一个类,来模拟“学生”属性 (是什么) 姓名 年龄行为(能做什么) 吃饭 睡觉 学习对应到Java的类当中 成员变量(属性) String nanme; //姓 ...

  9. 【C++ Primer 第15章】定义派生类析构函数

    学习资料 • 基类和派生类析构函数执行顺序 定义派生类析构函数 [注意]定义一个对象时先调用基类的构造函数.然后调用派生类的构造函数:析构的时候恰好相反:先调用派生类的析构函数.然后调用基类的析构函数 ...

  10. 【C++ Primer 第15章】定义派生类拷贝构造函数、赋值运算符

    学习资料 • 派生类的赋值运算符/赋值构造函数也必须处理它的基类成员的赋值 • C++ 基类构造函数带参数的继承方式及派生类的初始化 定义拷贝构造函数 [注意]对派生类进行拷贝构造时,如果想让基类的成 ...

随机推荐

  1. nchu第三次面向对象编程博客作业

    前言:   本次博客包含的内容有pta题目集6-8(电信计费)三次题目集.这次的难点主要是理解老师给的类图的内容,明白各部分的作用,以及如何使各类之间联系起来.只要能够理解老师给的类图结构之后就可以比 ...

  2. 【python】读取nc文件

    读取nc文件前的准备,安装一些库 1.先把几个用到的库下载 Cartopy 简介与安装(转载) - 简书 (jianshu.com) Python Extension Packages for Win ...

  3. Day17-JavaSE总结

    不多说了,直接去看视频吧! 链接 完结撒花!!!

  4. microbit问题记录

    问题: 1.电子罗盘东南西北:不太好用 2.    micropython代码:震动.声音显示不对 makecode代码:声音不好用 已解决: 1.摇杆下和左不管用了(已解决:改软件包代码) 2.ma ...

  5. js 获取鼠标位置的两种方法

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. element ui动态生成表单数据与校验(后台传入数据)

    前言 最近有一个需求是通过后台返回的数据,生成表单并添加校验.在做的过程中,动态表单挺好做,关键是校验.困扰了我2天,最后通过查找资料和"运气"终于解决了.解决问题关键点:vue的 ...

  7. 复制文件到U盘提示“一个意外错误使您无法复制该文件”处理办法

    运行cmd 运行 chkdsk H(U盘所在盘符):/f    即可

  8. 实验5 开源控制器实践——POX

    实验5 开源控制器实践--POX 一.实验目的 1.能够理解 POX 控制器的工作原理: 2.通过验证POX的forwarding.hub和forwarding.l2_learning模块,初步掌握P ...

  9. 02 HTML基础-图片和音视频

    1.HTML中的图片 HTML5的<figure>和<figcaption>为图片提供了一个语义容器,在标题和图片之间建立了清晰的联系.<figcaption>元素 ...

  10. element ui 全选反选

    <el-checkbox class="selectAll" :indeterminate="isIndeterminate" v-model=" ...