Spring扩展点系列-BeanFactoryAware

简介

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 {
    @Override
    public void setBeanName(String name) {
        log.info("ExtendBeanNameAware-2--beanName:{}",name);
    }

    @Override
    public 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;

    @Override
    public 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 {

    @Override
    public String toString() {
        return "这是 OtherBean 实例";
    }
}

@Configuration
public class AppConfig {
    @Bean
    public OtherBean getOtherBean () {
        return new OtherBean();
    }

    @Bean
    public 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;

    @Override
    public 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的名字为方法名
    @Bean
    public OtherBean getOtherBean () {
        return new OtherBean();
    }

    @Bean
    public 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();
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值