如何在靜態方法或非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);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM