Spring Boot - 扩展接口一览
/** Copyright 2002-2020 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** https://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package org.springframework.context.support;import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.EmbeddedValueResolver;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.ApplicationStartupAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.lang.Nullable;
import org.springframework.util.StringValueResolver;/*** {@link BeanPostProcessor} implementation that supplies the {@code ApplicationContext},* {@link org.springframework.core.env.Environment Environment}, or* {@link StringValueResolver} for the {@code ApplicationContext} to beans that* implement the {@link EnvironmentAware}, {@link EmbeddedValueResolverAware},* {@link ResourceLoaderAware}, {@link ApplicationEventPublisherAware},* {@link MessageSourceAware}, and/or {@link ApplicationContextAware} interfaces.** Implemented interfaces are satisfied in the order in which they are* mentioned above.**
Application contexts will automatically register this with their* underlying bean factory. Applications do not use this directly.** @author Juergen Hoeller* @author Costin Leau* @author Chris Beams* @since 10.10.2003* @see org.springframework.context.EnvironmentAware* @see org.springframework.context.EmbeddedValueResolverAware* @see org.springframework.context.ResourceLoaderAware* @see org.springframework.context.ApplicationEventPublisherAware* @see org.springframework.context.MessageSourceAware* @see org.springframework.context.ApplicationContextAware* @see org.springframework.context.support.AbstractApplicationContext#refresh()*/
class ApplicationContextAwareProcessor implements BeanPostProcessor {private final ConfigurableApplicationContext applicationContext;private final StringValueResolver embeddedValueResolver;/*** Create a new ApplicationContextAwareProcessor for the given context.*/public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {this.applicationContext = applicationContext;this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());}@Override@Nullablepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||bean instanceof ApplicationStartupAware)) {return bean;}AccessControlContext acc = null;if (System.getSecurityManager() != null) {acc = this.applicationContext.getBeanFactory().getAccessControlContext();}if (acc != null) {AccessController.doPrivileged((PrivilegedAction
ApplicationContextAwareProcessor
本身并没有扩展点,但是该类内部却有6个扩展点可供实现 ,这些类触发的时机在bean实例化之后,初始化之前.
5.3.2版本
private void invokeAwareInterfaces(Object bean) {if (bean instanceof EnvironmentAware) {((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());}if (bean instanceof EmbeddedValueResolverAware) {((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);}if (bean instanceof ResourceLoaderAware) {((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);}if (bean instanceof ApplicationEventPublisherAware) {((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);}if (bean instanceof MessageSourceAware) {((MessageSourceAware) bean).setMessageSource(this.applicationContext);}if (bean instanceof ApplicationStartupAware) {((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());}if (bean instanceof ApplicationContextAware) {((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);}}
EnvironmentAware
:用于获取EnviromentAware的一个扩展类,这个变量非常有用, 可以获得系统内的所有参数。个人认为这个Aware没必要去扩展,因为spring内部都可以通过注入的方式来直接获得。
EmbeddedValueResolverAware
:用于获取StringValueResolver的一个扩展类, StringValueResolver用于获取基于String类型的properties的变量,一般都用@Value的方式去获取,如果实现了这个Aware接口,把StringValueResolver缓存起来,通过这个类去获取String类型的变量,效果是一样的。
ResourceLoaderAware
:用于获取ResourceLoader的一个扩展类,ResourceLoader可以用于获取classpath内所有的资源对象,可以扩展此类来拿到ResourceLoader对象。
ApplicationEventPublisherAware
:用于获取ApplicationEventPublisher的一个扩展类,ApplicationEventPublisher可以用来发布事件,结合ApplicationListener来共同使用。这个对象也可以通过spring注入的方式来获得。
MessageSourceAware
:用于获取MessageSource的一个扩展类,MessageSource主要用来做国际化。
ApplicationStartupAware
: 要开始收集定制的StartupStep,组件可以实现ApplicationStartupAware接口直接获得ApplicationStartup实例或者在注入点请求ApplicationStartup类型。
ApplicationContextAware
:用来获取ApplicationContext的一个扩展类, ApplicationContext应该是很多人非常熟悉的一个类了,就是spring上下文管理器,可以手动的获取任何在spring上下文注册的bean,我们经常扩展这个接口来缓存spring上下文,包装成静态方法。同时ApplicationContext也实现了BeanFactory,MessageSource,ApplicationEventPublisher等接口,也可以用来做相关接口的事情。
org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization
我们继续看下 invokeAwareInterfaces(bean);
可知ApplicationContextAwareProcessor关联了大部分Spring内置Aware接口,它们的执行顺序如下:
EnvironmentAware -> EmbeddedValueResolverAware -> ResourceLoaderAware -> ApplicationEventPublisherAware -> MessageSourceAware -> ApplicationStartupAware -> ApplicationContextAware
我们来看下调用栈
org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors()BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);org.springframework.beans.factory.support.AbstractBeanFactory#getBeanorg.springframework.beans.factory.support.AbstractBeanFactory#doGetBean org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanorg.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBeanorg.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBeanapplyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);processor.postProcessBeforeInitialization(result, beanName);org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitializationorg.springframework.context.support.ApplicationContextAwareProcessor#invokeAwareInterfaces
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 {@Overridepublic void setBeanClassLoader(ClassLoader classLoader) {log.info(" ------> BeanClassLoaderAware::setBeanClassLoader invoked");}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {log.info(" ------> BeanFactoryAware::setBeanFactory invoked");}@Overridepublic void setBeanName(String s) {log.info(" ------> BeanNameAware::setBeanName invoked");}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {log.info(" ------> ApplicationContextAware::setApplicationContext invoked");}@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {log.info(" ------> ApplicationEventPublisherAware::setApplicationEventPublisher invoked");}@Overridepublic void setEmbeddedValueResolver(StringValueResolver resolver) {log.info(" ------> EmbeddedValueResolverAware::setEmbeddedValueResolver invoked");}@Overridepublic void setEnvironment(Environment environment) {log.info(" ------> EnvironmentAware::setEnvironment invoked");}@Overridepublic void setMessageSource(MessageSource messageSource) {log.info(" ------> MessageSourceAware::setMessageSource invoked");}@Overridepublic void setResourceLoader(ResourceLoader resourceLoader) {log.info(" ------> ResourceLoaderAware::setResourceLoader invoked");}@Overridepublic void setApplicationStartup(ApplicationStartup applicationStartup) {log.info(" ------> ApplicationStartup::setApplicationStartup invoked");}@Overridepublic void setImportMetadata(AnnotationMetadata importMetadata) {log.info(" ------> ImportAware::setImportMetadata invoked");}@Overridepublic 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