在项目中有时须要根据须要在本身new一个对象,或者在某些util方法或属性中获取Spring Bean对象,从而完成某些工做,可是因为本身new的对象和util方法并非受Spring所管理的,若是直接在所依赖的属性上使用@Autowired
就会报没法注入的错误,或者是没报错,可是使用的时候会报空指针异常。总而言之因为其是不受IoC容器所管理的,于是没法注入。java
Spring提供了两个接口:BeanFactoryAware和ApplicationContextAware,这两个接口都继承自Aware接口。以下是这两个接口的声明:spring
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:app
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); } }
这里还须要在配置文件中指定建立当前类的一个实例:dom
<bean id="springBeanFactory" class="com.business.util.SpringBeanUtil"/>
能够看到,咱们再SpringBeanUtil中声明了一个ApplicationContext类型的静态属性,而且在setApplicationContext()方法中将获取到的ApplicationContext赋值给了该静态属性,这样咱们就能够在另外两个声明的静态方法中经过ApplicationContext获取IoC容器所管理的bean了。以下是一个测试示例:ide
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,其实也很是简单,直接对属性赋值便可,以下所示:code
private static Student student = SpringBeanUtil.getBean(Student.class);