文章目录
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.info(" ------> EmbeddedValueResolverAware::setEmbeddedValueResolver invoked");
}
@Override
public void setEnvironment(Environment environment) {
log.info(" ------> EnvironmentAware::setEnvironment invoked");
}
@Override
public void setMessageSource(MessageSource messageSource) {
log.info(" ------> MessageSourceAware::setMessageSource invoked");
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
log.info(" ------> ResourceLoaderAware::setResourceLoader invoked");
}
@Override
public void setApplicationStartup(ApplicationStartup applicationStartup) {
log.info(" ------> ApplicationStartup::setApplicationStartup invoked");
}
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
log.info(" ------> ImportAware::setImportMetadata invoked");
}
@Override
public void setLoadTimeWeaver(LoadTimeWeaver loadTimeWeaver) {
log.info(" ------> LoadTimeWeaverAware::setLoadTimeWeaver invoked");
}
}
输出结果
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.4.2)
2022-12-04 19:14:25.103 INFO 12832 --- [ main] .b.t.ExtendApplicationContextInitializer : ExtendApplicationContextInitializer # initialize Called
2022-12-04 19:14:25.110 INFO 12832 --- [ main] c.a.b.BootSpringExtendApplication : Starting BootSpringExtendApplication using Java 1.8.0_261 on LAPTOP-JF3RBRRJ with PID 12832 (D:\IdeaProjects\boot2\boot-spring-extend\target\classes started by artisan in D:\IdeaProjects\boot2)
2022-12-04 19:14:25.111 INFO 12832 --- [ main] c.a.b.BootSpringExtendApplication : No active profile set, falling back to default profiles: default
2022-12-04 19:14:25.444 INFO 12832 --- [ main] c.a.b.testextends.ExtendInvokeAware : ------> BeanNameAware::setBeanName invoked
2022-12-04 19:14:25.444 INFO 12832 --- [ main] c.a.b.testextends.ExtendInvokeAware : ------> BeanClassLoaderAware::setBeanClassLoader invoked
2022-12-04 19:14:25.444 INFO 12832 --- [ main] c.a.b.testextends.ExtendInvokeAware : ------> BeanFactoryAware::setBeanFactory invoked
2022-12-04 19:14:25.444 INFO 12832 --- [ main] c.a.b.testextends.ExtendInvokeAware : ------> EnvironmentAware::setEnvironment invoked
2022-12-04 19:14:25.444 INFO 12832 --- [ main] c.a.b.testextends.ExtendInvokeAware : ------> EmbeddedValueResolverAware::setEmbeddedValueResolver invoked
2022-12-04 19:14:25.444 INFO 12832 --- [ main] c.a.b.testextends.ExtendInvokeAware : ------> ResourceLoaderAware::setResourceLoader invoked
2022-12-04 19:14:25.444 INFO 12832 --- [ main] c.a.b.testextends.ExtendInvokeAware : ------> ApplicationEventPublisherAware::setApplicationEventPublisher invoked
2022-12-04 19:14:25.444 INFO 12832 --- [ main] c.a.b.testextends.ExtendInvokeAware : ------> MessageSourceAware::setMessageSource invoked
2022-12-04 19:14:25.444 INFO 12832 --- [ main] c.a.b.testextends.ExtendInvokeAware : ------> ApplicationStartup::setApplicationStartup invoked
2022-12-04 19:14:25.444 INFO 12832 --- [ main] c.a.b.testextends.ExtendInvokeAware : ------> ApplicationContextAware::setApplicationContext invoked
2022-12-04 19:14:25.529 INFO 12832 --- [ main] c.a.b.BootSpringExtendApplication : Started BootSpringExtendApplication in 0.747 seconds (JVM running for 1.792)
Process finished with exit code 0