前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring - BeanFactoryAware扩展接口

Spring - BeanFactoryAware扩展接口

作者头像
小小工匠
发布2022-12-05 15:37:11
4480
发布2022-12-05 15:37:11
举报
文章被收录于专栏:小工匠聊架构

文章目录

在这里插入图片描述
在这里插入图片描述

Pre

Spring Boot - 扩展接口一览

在这里插入图片描述
在这里插入图片描述

org.springframework.beans.factory.BeanFactoryAware

代码语言:javascript
复制
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接口
代码语言:javascript
复制
ApplicationEventPublisherAware
MessageSourceAware
ResourceLoaderAware
BeanFactoryAware
EnvironmentAware
EmbeddedValueResolverAware
ImportAware
LoadTimeWeaverAware
BeanClassLoaderAware
BeanNameAware
ApplicationContextAware
  • Spring web内建的Aware接口
代码语言:javascript
复制
ServletContextAware
ServletConfigAware
  • Spring其它内建Aware接口
代码语言:javascript
复制
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)
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
processor.postProcessBeforeInitialization(result, beanName);

进入到

Spring内置的核心Aware BeanPostProcessor是ApplicationContextAwareProcessor

代码语言:javascript
复制
org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization
在这里插入图片描述
在这里插入图片描述

我们继续看下 invokeAwareInterfaces(bean);

在这里插入图片描述
在这里插入图片描述

可知ApplicationContextAwareProcessor关联了大部分Spring内置Aware接口,它们的执行顺序如下:

代码语言:javascript
复制
EnvironmentAware -> EmbeddedValueResolverAware -> ResourceLoaderAware -> ApplicationEventPublisherAware -> MessageSourceAware ->   ApplicationStartupAware -> ApplicationContextAware

结论: 直接方法调用的时机要早于通过BeanPostProcessor#postProcessBeforeInitialization调用的时机

由于Aware的接口的调用受到BeanPostProcessor的直接影响,因此BeanPostProcessor的执行顺序也就是Aware接口的调用顺序。


那刚才为啥直接跳到了 ApplicationContextAwareProcessor

我们看看可以看看ApplicationContextAwareProcessor的设置执行时机

AbstractApplicationContext#refresh方法

代码语言:javascript
复制
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

代码语言:javascript
复制
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        //....省略其余代码
        // Configure the bean factory with context callbacks.
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

      //....省略其余代码
}

可以看到 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)这里可以看到ApplicationContextAwareProcessor直接第一个加入到该BeanFactory中。


源码解析 (直接调用)

代码语言:javascript
复制
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方法中

重点看

代码语言:javascript
复制
	// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}

进入 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean

代码语言:javascript
复制
if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}

代码语言:javascript
复制
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods
代码语言:javascript
复制
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);
			}
		}
	}

看到了吧

代码语言:javascript
复制
if (bean instanceof BeanFactoryAware) {
		((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}

由以上代码片段可以得出结论:Aware接口执行顺序是

代码语言:javascript
复制
 BeanNameAware -> BeanClassLoaderAware -> BeanFactoryAware

调用链如下

代码语言:javascript
复制
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调用执行顺序)

其实上面最开始的截图里已经有了,我们再看下

代码语言:javascript
复制
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

代码语言:javascript
复制
//....省略
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
  wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
 //....省略
代码语言:javascript
复制
@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()中的

代码语言:javascript
复制
registerBeanPostProcessors(beanFactory);//向BeanFactory注入BeanPost

注册BeanPostProcessor的最终执行者是PostProcessorRegistrationDelegate.registerBeanPostProcessors

这其中的排序规则如下(针对于属于该BeanFactoryBeanPostProcessor BeanDefinition):

代码语言:javascript
复制
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
  • 实现了PriorityOrdered接口优先级最高, 再按order进行排序 小 -> 大
  • 其次是实现了Ordered接口, 再按order进行排序 小 -> 大
  • 其它的根据BeanDefinition Spring注册顺序来

当然还可以通过BeanFactoryPostProcessor来配置该BeanFactory, 举个例子ConfigurationClassPostProcessor

代码语言:javascript
复制
@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));
}
代码语言:javascript
复制
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

代码语言:javascript
复制
AbstractApplicationContext#prepareBeanFactory
代码语言:javascript
复制
// 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接口执行顺序如下:

代码语言:javascript
复制
BeanNameAware -> BeanClassLoaderAware -> BeanFactoryAware -> EnvironmentAware -> EmbeddedValueResolverAware -> ResourceLoaderAware -> ApplicationEventPublisherAware -> MessageSourceAware -> ApplicationContextAware -> ImportAware -> LoadTimeWeaverAware

扩展点示例

代码语言:javascript
复制
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());
    }
}

再看第二个比较全的扩展

代码语言:javascript
复制
 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");
    }


}

输出结果

代码语言:javascript
复制
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: 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
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-12-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • Pre
  • org.springframework.beans.factory.BeanFactoryAware
  • 扩展点说明
  • Aware接口
  • Spring内建Aware接口的执行时机及顺序
  • 源码解析 (直接调用)
  • 源码分析 (BeanPostProcessor调用执行顺序)
  • 扩展点示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档