Spring - BeanFactoryAware扩展接口
Posted 小小工匠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring - BeanFactoryAware扩展接口相关的知识,希望对你有一定的参考价值。
文章目录
- Pre
- org.springframework.beans.factory.BeanFactoryAware
- 扩展点说明
- Aware接口
- Spring内建Aware接口的执行时机及顺序
- 源码解析 (直接调用)
- 源码分析 (BeanPostProcessor调用执行顺序)
- 扩展点示例
Pre
org.springframework.beans.factory.BeanFactoryAware
package org.springframework.beans.factory;
import org.springframework.beans.BeansException;
/**
* Interface to be implemented by beans that wish to be aware of their
* owning @link BeanFactory.
*
* <p>For example, beans can look up collaborating beans via the factory
* (Dependency Lookup). Note that most beans will choose to receive references
* to collaborating beans via corresponding bean properties or constructor
* arguments (Dependency Injection).
*
* <p>For a list of all bean lifecycle methods, see the
* @link BeanFactory BeanFactory javadocs.
*
* @author Rod Johnson
* @author Chris Beams
* @since 11.03.2003
* @see BeanNameAware
* @see BeanClassLoaderAware
* @see InitializingBean
* @see org.springframework.context.ApplicationContextAware
*/
public interface BeanFactoryAware extends Aware
/**
* Callback that supplies the owning factory to a bean instance.
* <p>Invoked after the population of normal bean properties
* but before an initialization callback such as
* @link InitializingBean#afterPropertiesSet() or a custom init-method.
* @param beanFactory owning BeanFactory (never @code null).
* The bean can immediately call methods on the factory.
* @throws BeansException in case of initialization errors
* @see BeanInitializationException
*/
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
扩展点说明
扩展点方法为setBeanFactory
,可以拿到BeanFactory
这个属性。
使用场景:可以在bean实例化之后,但还未初始化之前,拿到 BeanFactory
,在这个时候,可以对每个bean进行特殊化的定制。也或者可以把BeanFactory
拿到进行缓存,日后使用。
Aware接口
- Spring core 和 context的内建Aware接口
ApplicationEventPublisherAware
MessageSourceAware
ResourceLoaderAware
BeanFactoryAware
EnvironmentAware
EmbeddedValueResolverAware
ImportAware
LoadTimeWeaverAware
BeanClassLoaderAware
BeanNameAware
ApplicationContextAware
- Spring web内建的Aware接口
ServletContextAware
ServletConfigAware
- Spring其它内建Aware接口
SchedulerContextAware (spring scheduling)
NotificationPublisherAware (spring jmx export)
BootstrapContextAware (spring jca)
Spring内建Aware接口的执行时机及顺序
Aware接口的执行时机肯定是在Spring Bean创建的时候。
对于Aware接口的执行实现主要有一下两种模式
- 初始化Bean(
initializeBean
)的时候直接进行方法调用 -> setXXXX BeanPostProcessor -> Object postProcessBeforeInitialization(Object bean, String beanName)
processor.postProcessBeforeInitialization(result, beanName);
进入到
Spring内置的核心Aware BeanPostProcessor是ApplicationContextAwareProcessor
org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization
我们继续看下 invokeAwareInterfaces(bean);
可知ApplicationContextAwareProcessor关联了大部分Spring内置Aware接口,它们的执行顺序如下:
EnvironmentAware -> EmbeddedValueResolverAware -> ResourceLoaderAware -> ApplicationEventPublisherAware -> MessageSourceAware -> ApplicationStartupAware -> ApplicationContextAware
结论: 直接方法调用的时机要早于通过BeanPostProcessor#postProcessBeforeInitialization
调用的时机
由于Aware的接口的调用受到BeanPostProcessor
的直接影响,因此BeanPostProcessor
的执行顺序也就是Aware接口的调用顺序。
那刚才为啥直接跳到了 ApplicationContextAwareProcessor
?
我们看看可以看看ApplicationContextAwareProcessor的设置执行时机
AbstractApplicationContext#refresh
方法
public void refresh() throws BeansException, IllegalStateException
synchronized (this.startupShutdownMonitor)
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
//....省略其余代码
继续看 prepareBeanFactory
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory)
//....省略其余代码
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//....省略其余代码
可以看到 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)
这里可以看到ApplicationContextAwareProcessor
直接第一个加入到该BeanFactory
中。
源码解析 (直接调用)
org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors()
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
org.springframework.beans.factory.support.AbstractBeanFactory#getBean
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
在 doCreateBean
方法中
重点看
// Initialize the bean instance.
Object exposedObject = bean;
try
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
进入 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean
if (System.getSecurityManager() != null)
AccessController.doPrivileged((PrivilegedAction<Object>) () ->
invokeAwareMethods(beanName, bean);
return null;
, getAccessControlContext());
else
invokeAwareMethods(beanName, bean);
看
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods
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);
看到了吧
if (bean instanceof BeanFactoryAware)
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
由以上代码片段可以得出结论:Aware接口执行顺序是
BeanNameAware -> BeanClassLoaderAware -> BeanFactoryAware
调用链如下
org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors()
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
org.springframework.beans.factory.support.AbstractBeanFactory#getBean
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods
源码分析 (BeanPostProcessor调用执行顺序)
其实上面最开始的截图里已经有了,我们再看下
org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors()
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
org.springframework.beans.factory.support.AbstractBeanFactory#getBean
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean
继续 initializeBean
看
//....省略
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic())
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
//....省略
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors())
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null)
return result;
result = current;
return result;
public List<BeanPostProcessor> getBeanPostProcessors()
return this.beanPostProcessors;
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
可知beanPostProcessors
是关联该BeanFactory
的有序列表, 这个列表的数据来源就是ConfigurableBeanFactory#addBeanPostProcessor(BeanPostProcessor beanPostProcessor)
这个方法。
回到AbstractApplicationContext#refresh()
中的
registerBeanPostProcessors(beanFactory);//向BeanFactory注入BeanPost
注册BeanPostProcessor
的最终执行者是PostProcessorRegistrationDelegate.registerBeanPostProcessors
这其中的排序规则如下(针对于属于该BeanFactory
的 BeanPostProcessor BeanDefinition
):
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
- 实现了PriorityOrdered接口优先级最高, 再按order进行排序 小 -> 大
- 其次是实现了Ordered接口, 再按order进行排序 小 -> 大
- 其它的根据BeanDefinition Spring注册顺序来
当然还可以通过BeanFactoryPostProcessor
来配置该BeanFactory, 举个例子ConfigurationClassPostProcessor
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId))
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + beanFactory);
this.factoriesPostProcessed.add(factoryId);
if (!this.registriesPostProcessed.contains(factoryId))
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
// Simply call processConfigurationClasses lazily at this point then.
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
enhanceConfigurationClasses(beanFactory);
//注册添加ImportAware接口处理器
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
private static class ImportAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
....
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
if (bean instanceof ImportAware)
ImportRegistry ir = this.beanFactory.getBean(IMPORT_REGISTRY_BEAN_NAME, ImportRegistry.class);
AnnotationMetadata importingClass = ir.getImportingClassFor(ClassUtils.getUserClass(bean).getName());
if (importingClass != null)
//ImportAware#setImportMetadata调用
((ImportAware) bean).setImportMetadata(importingClass);
return bean;
由以上可知ImportAware
执行顺序ApplicationContextAwareProcessor
关联的那些Aware接口之后执行。
其实还有一个 LoadTimeWeaverAwareProcessor
AbstractApplicationContext#prepareBeanFactory
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) //有条件的注入, 必须存在该bean或者bean definition
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
目前的Aware接口执行顺序如下:
BeanNameAware -> BeanClassLoaderAware -> BeanFactoryAware -> EnvironmentAware -> EmbeddedValueResolverAware -> ResourceLoaderAware -> ApplicationEventPublisherAware -> MessageSourceAware -> ApplicationContextAware -> ImportAware -> LoadTimeWeaverAware
扩展点示例
package com.artisan.bootspringextend.testextends;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.annotation.Configuration;
/**
* @author 小工匠
* @version 1.0
* @description: TODO
* @date 2022/12/4 9:53
* @mark: show me the code , change the world
*/
@Slf4j
@Configuration
public class ExtendBeanFactoryAware implements BeanFactoryAware
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException
log.info("----->ExtendBeanFactoryAware " , beanFactory.getBean(ExtendBeanFactoryAware.class).getClass().getSimpleName());
再看第二个比较全的扩展
package com.artisan.bootspringextend.testextends;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.*;
import org.springframework.context.annotation.ImportAware;
import org.springframework.context.weaving.LoadTimeWeaverAware;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.metrics.ApplicationStartup;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.instrument.classloading.LoadTimeWeaver;
import org.springframework.stereotype.Component;
import org.springframework.util.StringValueResolver;
/**
* @author 小工匠
* @version 1.0
* @description: TODO
* @date 2022/12/4 11:02
* @mark: show me the code , change the world
*/
@Slf4j
@Component
public class ExtendInvokeAware implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, EnvironmentAware, EmbeddedValueResolverAware,
ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware,ApplicationStartupAware, ApplicationContextAware, ImportAware,
LoadTimeWeaverAware
@Override
public void setBeanClassLoader(ClassLoader classLoader)
log.info(" ------> BeanClassLoaderAware::setBeanClassLoader invoked");
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException
log.info(" ------> BeanFactoryAware::setBeanFactory invoked");
@Override
public void setBeanName(String s)
log.info(" ------> BeanNameAware::setBeanName invoked");
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
log.info(" ------> ApplicationContextAware::setApplicationContext invoked");
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher)
log.info(" ------> ApplicationEventPublisherAware::setApplicationEventPublisher invoked");
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver)
log以上是关于Spring - BeanFactoryAware扩展接口的主要内容,如果未能解决你的问题,请参考以下文章