您的位置:首页 > 教育 > 培训 > Spring扩展点系列-BeanFactoryAware

Spring扩展点系列-BeanFactoryAware

2024/10/5 21:20:47 来源:https://blog.csdn.net/qq_32590535/article/details/142210400  浏览:    关键词:Spring扩展点系列-BeanFactoryAware

文章目录

    • 简介
    • 源码分析
    • 示例代码
      • 示例一:验证BeanFactoryAware执行顺序
      • 示例二:动态获取其他bean
      • 示例三:动态bean的状态

简介

spring容器中Bean的生命周期内所有可扩展的点的调用顺序
扩展接口 实现接口
ApplicationContextlnitializer initialize
AbstractApplicationContext refreshe
BeanDefinitionRegistryPostProcessor postProcessBeanDefinitionRegistry
BeanDefinitionRegistryPostProcessor postProcessBeanFactory
BeanFactoryPostProcessor postProcessBeanFactory
instantiationAwareBeanPostProcessor postProcessBeforelnstantiation
SmartlnstantiationAwareBeanPostProcessor determineCandidateConstructors
MergedBeanDefinitionPostProcessor postProcessMergedBeanDefinition
InstantiationAwareBeanPostProcessor postProcessAfterlnstantiation
SmartInstantiationAwareBeanPostProcessor getEarlyBeanReference
BeanNameAware setBeanName
BeanFactoryAware postProcessPropertyValues
ApplicationContextAwareProcessor invokeAwarelnterfaces
InstantiationAwareBeanPostProcessor postProcessBeforelnstantiation
@PostConstruct
InitializingBean afterPropertiesSet
FactoryBean getobject
SmartlnitializingSingleton afterSingletonslnstantiated
CommandLineRunner run
DisposableBeandestroy

BeanFactoryAware用于注入BeanFactory对象。我们可以访问创建该对象的BeanFactory 。借助 setBeanFactory()方法,我们将IoC 容器中的BeanFactory引用分配给beanFactory 属性,之后,我们可以创建函数直接使用它。
BeanNameAware的常用场景一般是用于日志记录。

源码分析

BeanFactoryAware是Aware的超级子接口
在这里插入图片描述

从源码中可以看到BeanFactoryAware只提供了一个set方法,该接口中只定义了setBeanFactory一个方法。

public interface BeanFactoryAware extends Aware {void setBeanFactory(BeanFactory beanFactory) throws BeansException;}

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean实现了Spring的Aware接口族的Beans(如BeanNameAware, BeanFactoryAware等)。如果提供的bean实现了任何这些接口,该方法会回调相应的Aware方法

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;
}

当一个 bean 实现了如 BeanNameAware、BeanClassLoaderAware 或 BeanFactoryAware 等接口时,此方法确保正确的回调方法被调用,从而为 bean 提供关于其运行环境或其他相关信息。

private void invokeAwareMethods(String beanName, Object bean) {if (bean instanceof Aware) {if (bean instanceof BeanNameAware) {((BeanNameAware) bean).setBeanName(beanName);}if (bean instanceof BeanClassLoaderAware) {ClassLoader bcl = getBeanClassLoader();if (bcl != null) {((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);}}if (bean instanceof BeanFactoryAware) {((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);}}
}

示例代码

示例一:验证BeanFactoryAware执行顺序

这里创建一个类去实现BeanFactoryAware,顺带也实现 BanNameAware接口,这样可以比对看出两者的执行顺序

@Slf4j
@Component
public class ExtendBeanFactoryAware implements BeanNameAware, BeanFactoryAware {@Overridepublic void setBeanName(String name) {log.info("ExtendBeanNameAware-2--beanName:{}",name);}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {log.info("ExtendBeanFactoryAware-3--beanName:{}",beanFactory);}
}

注:如果把@Component缓存@Configuration,setBeanFactory会执行两次。setBeanFactory-》setBeanName=》setBeanFactory
运行示例
在这里插入图片描述

示例二:动态获取其他bean

下面这个示例主要展示一个常用的场景,一个 Bean 可以在运行时动态获取其他 Bean

@Slf4j
@Component
public class ExtendBeanFactoryAware implements BeanNameAware, BeanFactoryAware {private BeanFactory beanFactory;@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {this.beanFactory = beanFactory;log.info("ExtendBeanFactoryAware-3--beanName:{}",beanFactory);}public void getOtherBean() {OtherBean otherBean = beanFactory.getBean(OtherBean.class);System.out.println("获取 otherBean 实例: " + otherBean);}
}@Component
public class OtherBean {@Overridepublic String toString() {return "这是 OtherBean 实例";}
}@Configuration
public class AppConfig {@Beanpublic OtherBean getOtherBean () {return new OtherBean();}@Beanpublic ExtendBeanFactoryAware getExtendBeanFactoryAware () {return new ExtendBeanFactoryAware();}
}//controller运行调用获取bean
@GetMapping("/getOtherBean")
public void getOtherBean() throws Exception{ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);ExtendBeanFactoryAware beanFactoryAware = context.getBean(ExtendBeanFactoryAware.class);beanFactoryAware.getOtherBean();
}

运行示例
在这里插入图片描述

示例三:动态bean的状态

在运行时,可以通过 BeanFactoryAware检查某个 Bean 是否存在或者其状态,下面是代码展示

@Slf4j
@Component
public class ExtendBeanFactoryAware implements BeanNameAware, BeanFactoryAware {private BeanFactory beanFactory;@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {this.beanFactory = beanFactory;log.info("ExtendBeanFactoryAware-3--beanName:{}",beanFactory);}public void checkBeanState() {boolean exists = beanFactory.containsBean("getOtherBean");log.info("otherBean 是否存在: {}" , exists);}
}@Component
public class OtherBean {
}@Configuration
public class AppConfig {//如果不指定Bean名,则默认是bean的名字为方法名@Beanpublic OtherBean getOtherBean () {return new OtherBean();}@Beanpublic ExtendBeanFactoryAware getExtendBeanFactoryAware () {return new ExtendBeanFactoryAware();}
}//controller运行调用获取bean
@GetMapping("/checkBeanState")
public void checkBeanState() throws Exception{ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);ExtendBeanFactoryAware beanFactoryAware = context.getBean(ExtendBeanFactoryAware.class);beanFactoryAware.checkBeanState();
}

运行示例
在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com