zoukankan      html  css  js  c++  java
  • 如何在静态方法或非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);
    
  • 相关阅读:
    Java实现 LeetCode 802 找到最终的安全状态 (DFS)
    Java实现 LeetCode 802 找到最终的安全状态 (DFS)
    Java实现 LeetCode 802 找到最终的安全状态 (DFS)
    Java实现 LeetCode 804 唯一摩尔斯密码词 (暴力)
    Java实现 LeetCode 803 打砖块 (DFS)
    Java实现 LeetCode 804 唯一摩尔斯密码词 (暴力)
    Java实现 LeetCode 803 打砖块 (DFS)
    Java实现 LeetCode 804 唯一摩尔斯密码词 (暴力)
    英文标点
    post sharp 与log4net 结合使用,含执行源码 转拷
  • 原文地址:https://www.cnblogs.com/zhangxufeng/p/9162184.html
Copyright © 2011-2022 走看看