在项目中有时需要根据需要在自己 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);
来源: http://www.bubuko.com/infodetail-2638342.html