百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 文章教程 > 正文

Spring ApplicationContextAware使用理解

xsobi 2024-11-24 23:34 2 浏览

问题背景

在我们的web程序中,用spring来管理各个实例(bean), 有时在程序中为了使用已被实例化的bean, 通常会用到这样的代码:

ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext-common.xml");
AbcService abcService = (AbcService)appContext.getBean("abcService");

但是这样就会存在一个问题:因为它会重新装载applicationContext-common.xml并实例化上下文bean,如果有些线程配置类也是在这个配置文件中,那么会造成做相同工作的的线程会被启两次。一次是web容器初始化时启动,另一次是上述代码显示的实例化了一次。当于重新初始化一遍!!!!这样就产生了冗余。

解决方法

不用类似new ClassPathXmlApplicationContext()的方式,从已有的spring上下文取得已实例化的bean。通过ApplicationContextAware接口进行实现。

当一个类实现了这个接口(ApplicationContextAware)之后,这个类就可以方便获得ApplicationContext中的所有bean。换句话说,就是这个类可以直接获取spring配置文件中,所有有引用到的bean对象。

ApplicationContextAware怎么用

(1)方法类AppUtil实现ApplicationContextAware接口

@Component
public class AppUtil implements ApplicationContextAware {

private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext arg0) throws BeansException {
applicationContext = arg0;
}

public static Object getObject(String id) {
Object object = null;
object = applicationContext.getBean(id);
return object;
}
}

【备注】

(1)在spring的配置文件中,注册方法类AppUtil。之所以方法类AppUtil能够灵活自如地获取ApplicationContext,就是因为spring能够为我们自动地执行了setApplicationContext。但是,spring不会无缘无故地为某个类执行它的方法的,所以,就很有必要通过注册方法类AppUtil的方式告知spring有这样子一个类的存在。这里我们使用@Component来进行注册,或者我们也可以像下面这样在配置文件声明bean:

<bean id="appUtil" class="com.htsoft.core.util.AppUtil"/>

(2)加载Spring配置文件时,如果Spring配置文件中所定义的Bean类实现了ApplicationContextAware 接口,那么在加载Spring配置文件时,会自动调用ApplicationContextAware 接口中的

public void setApplicationContext(ApplicationContext context) throws BeansException

方法,获得ApplicationContext对象,ApplicationContext对象是由spring注入的。前提必须在Spring配置文件中指定该类。

(3)使用静态的成员ApplicationContext类型的对象。

使用场景备注

从ApplicationContextAware获取ApplicationContext上下文的情况,仅仅适用于当前运行的代码和已启动的Spring代码处于同一个Spring上下文,否则获取到的ApplicationContext是空的。

比如我要为当前系统加入一个定时任务,定时刷新Memcache缓存。这个定时任务框架是公司的框架,下面是我的ApplicationContextAware 接口实现类:

@Component
public class ApplicationContextUtil implements ApplicationContextAware {

private static ApplicationContext applicationContext;//声明一个静态变量保存

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("applicationContext正在初始化,application:"+appContext);
this.applicationContext=applicationContext;
}

public static <T> T getBean(Class<T> clazz){
if(applicationContext==null){
System.out.println("applicationContext是空的");
}else{
System.out.println("applicationContext不是空的");
}
return applicationContext.getBean(clazz);
}

public static ApplicationContext getApplicationContext(){
return applicationContext;
}
}

定时任务类如下,定时任务初始化的时候,首先会调用作业类的public static Object getObject()方法返回作业类的实例。

@Component
public class RemoteCacheJob extends AbstractSaturnJavaJob {

@Autowired
private AdsRemoteCacheJob adsRemoteCacheJob;

@Autowired
private ILogService logService;

// 实例化的过程:系统会首先调用作业类的public static Object getObject()方法,
// 如果返回为null,则调用作业类的无参构造方法来实例化;否则直接使用getObject()方法返回的对象作为作业类实例。
public static Object getObject() {
return ApplicationContextUtil.getBean(RemoteCacheJob .class);
}

@Override
public void handleJavaJob(String jobName, Integer shardItem, String shardParam, SaturnJobExecutionContext shardingContext)
throws InterruptedException {
System.out.println("处理定时任务");
}
}

启动项目,Spring容器进行初始化,可以看到已经初始化了ApplicationContext :

然后运行定时任务插件,首先去获取ApplicationContext,但是此时的applicationContext是空的:

很显然,定时任务是没办法获取到项目所在Spring容器启动之后的ApplicationContext。

相关推荐

js向对象中添加元素(对象,数组) js对象里面添加元素

一、添加一个元素对象名["属性名"]=值(值:可以是一个值,可以是一个对象,也可以是一个数组)这样添加进去的元素,就是一个值或对象或数组...

JS小技巧,如何去重对象数组?(一)

大家好,关于数组对象去重的业务场景,想必大家都遇到过类似的需求吧,这对这样的需求你是怎么做的呢。下面我就先和大家分享下如果是基于对象的1个属性是怎么去重实现的。方法一:使用.filter()和....

「C/C++」之数组、vector对象和array对象的比较

数组学习过C语言的,对数组应该都不会陌生,于是这里就不再对数组进行展开介绍。模板类vector模板类vector类似于string,也是一种动态数组。能够在运行阶段设置vector对象的长度,可以在末...

如何用sessionStorage保存对象和数组

背景:在工作中,我将[{},{}]对象数组形式,存储到sessionStorage,然后ta变成了我看不懂的形式,然后我想取之用之,发现不可能了~记录这次深刻的教训。$clickCouponIndex...

JavaScript Array 对象 javascript的array对象

Array对象Array对象用于在变量中存储多个值:varcars=["Saab","Volvo","BMW"];第一个数组元素的索引值为0,第二个索引值为1,以此类推。更多有...

JavaScript中的数组Array(对象) js array数组

1:数组Array:-数组也是一个对象-数组也是用来存储数据的-和object不同,数组中可以存储一组有序的数据,-数组中存储的数据我们称其为元素(element)-数组中的每一个元素都有一...

数组和对象方法&amp;数组去重 数组去重的5种方法前端

列举一下JavaScript数组和对象有哪些原生方法?数组:arr.concat(arr1,arr2,arrn);--合并两个或多个数组。此方法不会修改原有数组,而是返回一个新数组...

C++ 类如何定义对象数组?初始化数组?linux C++第43讲

对象数组学过C语言的读者对数组的概念应该很熟悉了。数组的元素可以是int类型的变量,例如int...

ElasticSearch第六篇:复合数据类型-数组,对象

在ElasticSearch中,使用JSON结构来存储数据,一个Key/Value对是JSON的一个字段,而Value可以是基础数据类型,也可以是数组,文档(也叫对象),或文档数组,因此,每个JSON...

第58条:区分数组对象和类数组对象

示例设想有两个不同类的API。第一个是位向量:有序的位集合varbits=newBitVector;bits.enable(4);bits.enable([1,3,8,17]);b...

八皇后问题解法(Common Lisp实现)

如何才能在一张国际象棋的棋盘上摆上八个皇后而不致使她们互相威胁呢?这个著名的问题可以方便地通过一种树搜索方法来解决。首先,我们需要写一个函数来判断棋盘上的两个皇后是否互相威协。在国际象棋中,皇后可以沿...

visual lisp修改颜色的模板函数 怎么更改visual studio的配色

(defunBF-yansemokuai(tuyuanyanse/ss)...

用中望CAD加载LISP程序技巧 中望cad2015怎么加载燕秀

1、首先请加载lisp程序,加载方法如下:在菜单栏选择工具——加载应用程序——添加,选择lisp程序然后加载,然后选择添加到启动组。2、然后是添加自定义栏以及图标,方法如下(以...

图的深度优先搜索和广度优先搜索(Common Lisp实现)

为了便于描述,本文中的图指的是下图所示的无向图。搜索指:搜索从S到F的一条路径。若存在,则以表的形式返回路径;若不存在,则返回nil。...

两个有助于理解Common Lisp宏的例子

在Lisp中,函数和数据具有相同的形式。这是Lisp语言的一个重大特色。一个Lisp函数可以分析另一个Lisp函数;甚至可以和另一个Lisp函数组成一个整体,并加以利用。Lisp的宏,是实现上述特色的...