Spring - ApplicationContextAwareProcessor扩展接口

简介: ApplicationContextAwareProcessor扩展接口

@[toc]

在这里插入图片描述


Pre

Spring Boot - 扩展接口一览

在这里插入图片描述


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      :  ------> 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

在这里插入图片描述

相关文章
|
4天前
|
Java API 微服务
【Spring Boot系列】通过OpenAPI规范构建微服务服务接口
【4月更文挑战第5天】通过OpenAPI接口构建Spring Boot服务RestAPI接口
|
4天前
|
前端开发 安全 Java
Spring Boot 三招组合拳,手把手教你打出优雅的后端接口
Spring Boot 三招组合拳,手把手教你打出优雅的后端接口
45 0
|
4天前
|
Java Spring
spring boot访问接口报500
spring boot访问接口报500
13 2
|
4天前
|
Java 数据库连接 数据库
spring+mybatis_编写一个简单的增删改查接口
spring+mybatis_编写一个简单的增删改查接口
17 2
|
4天前
|
算法 NoSQL Java
限流艺术:Spring Boot接口限流的实用指南
限流艺术:Spring Boot接口限流的实用指南
104 0
限流艺术:Spring Boot接口限流的实用指南
|
4天前
|
负载均衡 网络协议 Java
构建高效可扩展的微服务架构:利用Spring Cloud实现服务发现与负载均衡
本文将探讨如何利用Spring Cloud技术实现微服务架构中的服务发现与负载均衡,通过注册中心来管理服务的注册与发现,并通过负载均衡策略实现请求的分发,从而构建高效可扩展的微服务系统。
|
4天前
|
数据采集 前端开发 NoSQL
Spring Boot反爬虫,防止接口盗刷
Spring Boot反爬虫,防止接口盗刷
26 1
|
4天前
ssm(Spring+Spring mvc+mybatis)Dao接口——IDeptDao
ssm(Spring+Spring mvc+mybatis)Dao接口——IDeptDao
9 0
|
4天前
|
Java Spring
使用JDBCTemplate实现与Spring结合,方法公用 ——接口(BaseDao)
使用JDBCTemplate实现与Spring结合,方法公用 ——接口(BaseDao)
9 0
|
4天前
|
存储 Java 数据处理
Spring揭秘:ClassPathScanningProvider接口应用场景及实现原理!
ClassPathScanningCandidateComponentProvider是Spring框架中一个非常核心的类,它主要用于在类路径下扫描并发现带有特定注解的组件,支持诸如@ComponentScan、@Component、@Service、@Repository和@Controller等注解的自动扫描和注册。
Spring揭秘:ClassPathScanningProvider接口应用场景及实现原理!