如何在静态方法或非Spring Bean中注入Spring Bean
在项目中有时需要根据需要在自己new一个对象,或者在某些util方法或属性中获取Spring Bean对象,从而完成某些工作,但是由于自己new的对象和util方法并不是受Spring所管理的,如果直接在所依赖的属性上使用@Autowired就会报无法注入的错误,或者是没报错,但是使用的时候会报空指针异常。总而言之由于其是不受IoC容器所管理的,因而无法注入。
Spring提供了两个接口:BeanFactoryAware和ApplicationContextAware,这两个接口都继承自Aware接口。如下是这两个接口的声明:
public interface BeanFactoryAware extends Aware {
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
在Spring官方文档中描述,在初始化Spring bean时,如果检测到某个bean实现了这两个接口中的一个,那么就会自动调用该bean所实现的接口方法。这里可以看到,这两个方法都是将IoC容器管理bean的工厂对象传递给当前bean,也就是说如果我们在当前bean中将工厂对象保存到某个静态属性中,那么我们就能够通过工厂对象获取到我们需要的bean。如下是使用ApplicationContextAware实现的一个SpringBeanUtil:
public class SpringBeanUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
SpringBeanUtil.applicationContext = applicationContext;
}
public static <T> T getBean(Class<T> clazz) {
return (T) applicationContext.getBean(clazz);
}
public static Object getBean(String name) throws BeansException {
return applicationContext.getBean(name);
}
}
这里还需要在配置文件中指定创建当前类的一个实例:
<bean id="springBeanFactory" class="com.business.util.SpringBeanUtil"/>
可以看到,我们再SpringBeanUtil中声明了一个ApplicationContext类型的静态属性,并且在setApplicationContext()方法中将获取到的ApplicationContext赋值给了该静态属性,这样我们就可以在另外两个声明的静态方法中通过ApplicationContext获取IoC容器所管理的bean了。如下是一个测试示例:
public class ClassRoom {
public void describeStudent() {
Student student = SpringBeanUtil.getBean(Student.class);
System.out.println(student);
}
public static void describeClassRoomCapacity() {
Student student = SpringBeanUtil.getBean(Student.class);
System.out.println("Is it not empty? " + (null != student));
}
}
public class Student {
@Override
public String toString() {
return "I am a student.";
}
}
<bean id="springBeanFactory" class="com.util.SpringBeanUtil"/>
<bean id="student" class="com.domain.Student"/>
如下是驱动类:
public class BeanApp {
public static void main(String[] args) {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("com/resources/application.xml");
ClassRoom.describeClassRoomCapacity();
ClassRoom classRoom = new ClassRoom();
classRoom.describeStudent();
}
}
在驱动类中,我们首先使用ClassPathXmlApplicationContext加载配置文件中的bean。可以看到,我们创建了一个SpringBeanUtil和一个Student的bean。我们首先在静态方法中获取了Student实例,并将其打印出来了,我们也在new出来的ClassRoom实例中通过SpringBeanUtil获取了Student实例,并且对其进行了输出。如下是输出结果:
Is it not empty? true
I am a student.
可以看到,无论是在静态方法中,还是在手动new的实例中,我们都成功获取了IoC容器所管理的bean。如果我们想在静态属性中获取SpringBean,其实也非常简单,直接对属性赋值即可,如下所示:
private static Student student = SpringBeanUtil.getBean(Student.class);
如何在静态方法或非Spring Bean中注入Spring Bean的更多相关文章
- 在非spring组件中注入spring bean
1.在spring中配置如下<context:spring-configured/> <context:load-time-weaver aspectj-weaving=&q ...
- spring中如何向一个单例bean中注入非单例bean
看到这个题目相信很多小伙伴都是懵懵的,平时我们的做法大都是下面的操作 @Component public class People{ @Autowired private Man man; } 这里如 ...
- Java(多)线程中注入Spring的Bean
问题说明 今天在web应用中用到了Java多线程的技术来并发处理一些业务,但在执行时一直会报NullPointerException的错误,问题定位了一下发现是线程中的Spring bean没有被注入 ...
- 【转】Java(多)线程中注入Spring的Bean
问题说明 今天在web应用中用到了Java多线程的技术来并发处理一些业务,但在执行时一直会报NullPointerException的错误,问题定位了一下发现是线程中的Spring bean没有被注入 ...
- 获取并打印Spring容器中所有的Bean名称
思路: 1.实现Spring的ApplicationContextAware接口,重写setApplicationContext方法,将得到的ApplicationContext对象保存到一个静态变量 ...
- Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->Spring Framework中的spring web MVC模块
spring framework中的spring web MVC模块 1.概述 spring web mvc是spring框架中的一个模块 spring web mvc实现了web的MVC架构模式,可 ...
- Spring Boot中使用 Spring Security 构建权限系统
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配置的Bean,为应用系统提供声明式的安全 ...
- 通过spring.net中的spring.caching CacheResult实现memcached缓存
通过spring.net中的spring.caching CacheResult实现memcached缓存1.SpringMemcachedCache.cs2.APP.config3.Program. ...
- Spring Boot动态注入删除bean
Spring Boot动态注入删除bean 概述 因为如果采用配置文件或者注解,我们要加入对象的话,还要重启服务,如果我们想要避免这一情况就得采用动态处理bean,包括:动态注入,动态删除. 动态注入 ...
随机推荐
- Spring源码分析(十二)FactoryBean的使用
摘要:本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 一般情况下,Spring通过反射机制利用bean的class属性指定实现 ...
- JS基础-组成
类型 前缀 类型 实例 数组 a Array aItems 布尔值 b Boolean bIsComplete 浮点数 f Float fPrice 函数 fn Function fnHandler ...
- PHP 抓取函数curl 实践
最近在学习curl的抓取实践, 在里面也学到了一些东西. 有一些网站需要cookie才可以抓取成功.这个时候我们就可以通过fiddle4 去抓包实现.然后通过构建头部信息 ,绕过网站端的验证. 以下是 ...
- ETL项目2:大数据清洗,处理:使用MapReduce进行离线数据分析并报表显示完整项目
ETL项目2:大数据清洗,处理:使用MapReduce进行离线数据分析并报表显示完整项目 思路同我之前的博客的思路 https://www.cnblogs.com/symkmk123/p/101974 ...
- ubuntu 9.10 切换到root用户
昨天装了ubuntu9.10,登陆后是普通用户,操作不方便,上网上查了资料,有很多方法,我发现最简单的方法 有些资料说,ubuntu每次重启root密码是随机的(当你没有设置密码时), 打开终端: $ ...
- Python虚拟环境包导出
一.导出包文件 1.进入虚拟环境 2.进入项目目录下创建放置包文件的文件夹(whls) mkdir whls 3.进入whls文件夹,执行导出命令 (导入包时有网络) cd whls pip free ...
- c++ 二叉树的遍历
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> ...
- Caffe中Layer注册机制
Caffe内部维护一个注册表用于查找特定Layer对应的工厂函数(Layer Factory的设计用到了设计模式里的工厂模式).Caffe的Layer注册表是一组键值对(key, value)( La ...
- Gitlab+Jenkins学习之路(九)之Jenkins的远程管理和集群
一.Jenkins的远程管理 Jenkins的远程管理方式包含: Shell ssh SSH Plugin ansible.saltstack (1)Shell ssh在项目构建时,jenkins使用 ...
- 128 C语言实现文件复制功能(包括文本文件和二进制文件)
文件的复制是常用的功能,要求写一段代码,让用户输入要复制的文件以及新建的文件,然后对文件进行复制.能够复制的文件包括文本文件和二进制文件,你可以复制1G的电影,也可以复制1Byte的txt文档. 实现 ...