需求:使用 @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. Git,GitHub与GitLab的区别

    Git是一种版本控制系统,是一种工具,用于代码的存储和版本控制. GitHub是一个基于Git实现的在线代码仓库,是目前全球最大的代码托管平台,可以帮助程序员之间互相交流和学习. GitLab是一个基 ...

  2. ASCII,unicode与utf-8的区别

    ASCII,unicode与utf-8的区别: ASCII码只有127个字母被编到计算机中,无法处理中文,ASCII 编码是 1 个字节 unicode是为了解决因各国标准不同而产生乱码的问题.uni ...

  3. 26、EXCEL—插入的文字,如何修改其内的边间距

    在形状格式-文本选项里面设置文本框的间距

  4. springboot整合mybatis:查询语句,返回null

    springboot整合mybatis时,查询数据库数据时,返回结果为null; 刚开始以为是数据库没连接上,结果增.改.删的其他语句则执行成功: 但唯有查询语句始终返回null,一条数据一个null ...

  5. CentOS7安装 Redis5 单实例

    1.下载redis下载地址在:redis.io比如把Redis安装到/usr/local/soft/ cd /usr/local/soft/ wget http://download.redis.io ...

  6. PHP实现微信提现V3版本2022-5更新接口:商家转账到零钱

    微信官方又更新了接口... V3版本的微信商家转账到零钱的接口---俗称提现接口 注意事项 一:开通条件:需满足入驻满90天,连续正常交易30天,保持正常健康交易.二:分为页面发起和api接口操作,均 ...

  7. npm安装时加 --save和不加的区别

    npm install xxx --save 命令是安装模块到项目node_modules目录下,会将模块依赖写入package.json文件中的dependencies{}下.如果将node_mod ...

  8. 10.10 2020 实验 6:OpenDaylight 实验——OpenDaylight 及 Postman 实现流表下发

    一.实验目的 熟悉 Postman 的使用:熟悉如何使用 OpenDaylight 通过 Postman 下发流表.   二.实验任务 推荐阅读:SDNLAB 文章:OpenFlow 协议超时机制简介 ...

  9. springboot修改事务隔离级别

    [SpringBoot]事务的隔离级别.Spring的事务传播机制_51CTO博客_springboot事务隔离级别

  10. MySql 入门——日期计算

    MySQL自带的日期函数TIMESTAMPDIFF计算两个日期相差的秒数.分钟数.小时数.天数.周数.季度数.月数.年数,当前日期增加或者减少一天.一周等等 SELECT TIMESTAMPDIFF( ...