Spring Boot - 扩展接口一览
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}.
*
* 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).
*
*
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.
* 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
拿到进行缓存,日后使用。
ApplicationEventPublisherAware
MessageSourceAware
ResourceLoaderAware
BeanFactoryAware
EnvironmentAware
EmbeddedValueResolverAware
ImportAware
LoadTimeWeaverAware
BeanClassLoaderAware
BeanNameAware
ApplicationContextAware
ServletContextAware
ServletConfigAware
SchedulerContextAware (spring scheduling)
NotificationPublisherAware (spring jmx export)
BootstrapContextAware (spring jca)
Aware接口的执行时机肯定是在Spring Bean创建的时候。
对于Aware接口的执行实现主要有一下两种模式
initializeBean
)的时候直接进行方法调用 -> setXXXXBeanPostProcessor -> 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
其实上面最开始的截图里已经有了,我们再看下
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);
当然还可以通过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