BeanFactoryAware 是 Spring 框架中的一个接口,它允许一个 bean 在其初始化时感知到其所在的 BeanFactory。这通常用于在 bean 内部进行一些高级配置或访问 Spring 容器中的其他 bean。
简单使用
当你实现 BeanFactoryAware 接口时,你需要实现 setBeanFactory(BeanFactory beanFactory) 方法。Spring 容器会在 bean 的初始化过程中自动调用这个方法,并传入当前的 BeanFactory 实例。说人话就是,如果在写代码当中需要使用到当前的BeanFactory 来创建自己定义的Bean时,我们需要拿到BeanFactory对象的,我们可不可以直接在当前上下文中直接调用getBeanFactory()方法来获取呢?答案是并没有提供这么一个方法类主动获取,但是Spring提供了BeanFactoryAware 接口,让你被动获取,也就是回调给你BeanFactory对象。
/**
* 实现 BeanFactoryAware 接口,获取 Bean工厂对象。
*/
public static class XRedisRegister implements BeanFactoryAware {
private BeanFactory beanFactory; // 重新BeanFactoryAware的方法,让spring回调来注入
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public void myFunction(){
// 可以使用 beanFactory 来做一些事情
}
}
实现机制
从spring源码中看aware接口在bean加载时的调用情况,BeanFactoryAware 接口很简单,只是继承了Aware来做第一重判断,在Spring通过反射获取各个Bean的时候会进行类型判断,如果是 BeanFactoryAware 的实现类则会进行BeanFactory注入。在Spring中的源码如下:
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
补充扩展
Spring的依赖注入的最大亮点就是你所有的Bean对Spring容器的存在是没有意识的。即你可以将你的容器替换成别的容器,例如Goggle Guice,这时Bean之间的耦合度很低。
但是在实际的项目中,我们不可避免的要用到Spring容器本身的功能资源,这时候Bean必须要意识到Spring容器的存在,才能调用Spring所提供的资源,这就是所谓的Spring Aware。其实Spring Aware本来就是Spring设计用来框架内部使用的,若使用了Spring Aware,你的Bean将会和Spring框架耦合。
Spring提供的Aware接口如下表所示:
接口 | 作用 |
---|---|
BeanNameAware | 获得到容器中Bean的名称 |
BeanFactoryAware | 获得当前bean factory,这样可以调用容器的服务 |
ApplicationContextAware | 获得当前application context,这样可以调用容器的服务 |
MessageSourceAware | 获得message source这样可以获得文本信息 |
ApplicationEventPublisherAware | 应用事件发布器,可以发布事件 |
ResourceLoaderAware | 获得资源加载器,可以获得外部资源文件 |
Spring Aware的目的是为了让Bean获得Spring容器的服务。因为ApplicationContext接口集成了MessageSource接口,ApplicationEventPublisherAware接口和ResourceLoaderAware接口,所以Bean继承ApplicationContextAware可以获得Spring容器的所有服务,但原则上我们还是用到什么接口就实现什么接口。
参考:
https://www.cnblogs.com/duanxz/p/3724429.html
https://yiyan.baidu.com/