zoukankan      html  css  js  c++  java
  • 如何在静态方法或非Spring Bean中注入Spring Bean

    如何在静态方法或非Spring Bean中注入Spring Bean

    原文链接:https://www.cnblogs.com/zhangxufeng/p/9162184.html

    在项目中有时需要根据需要在自己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);
    


    作者:不敲代码的攻城狮
    出处:https://www.cnblogs.com/leigq/
    任何傻瓜都能写出计算机可以理解的代码。好的程序员能写出人能读懂的代码。

     
  • 相关阅读:
    关于“平台”概念的解析
    学习新名词“MVP”(最简可行产品)
    Docker 部署Spring boot 项目如何优雅的关闭(Eureka下线)
    微服务健康监控方案
    Cpu飚高show-busy-java-threads一件脚本排查与Arthas线上诊断工具排查实战
    微服务发展规划(PS 大概分层未细化到具体系统)
    前后端分离研究
    Graphics2D画快递电子面单图片并且打印
    改写rm -rf 脚本
    检查系统信息脚本
  • 原文地址:https://www.cnblogs.com/leigq/p/13406580.html
Copyright © 2011-2022 走看看