Spring - ApplicationContextAwareProcessor扩展接口
Posted 小小工匠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring - ApplicationContextAwareProcessor扩展接口相关的知识,希望对你有一定的参考价值。
文章目录
Pre
org.springframework.context.support.ApplicationContextAwareProcessor
/*
* 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.
*
* <p>Implemented interfaces are satisfied in the order in which they are
* mentioned above.
*
* <p>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
@Nullable
public 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<Object>) () ->
invokeAwareInterfaces(bean);
return null;
, acc);
else
invokeAwareInterfaces(bean);
return bean;
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);
ApplicationContextAwareProcessor
本身并没有扩展点,但是该类内部却有6个扩展点可供实现 ,这些类触发的时机在bean实例化之后,初始化之前.
内部的7个扩展点
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#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
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
processor.postProcessBeforeInitialization(result, beanName);
org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization
org.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
@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 : ----以上是关于Spring - ApplicationContextAwareProcessor扩展接口的主要内容,如果未能解决你的问题,请参考以下文章
ContextLoader和ContextLoaderListener