• 2.spring源码-BeanPostProcessor后置处理之ApplicationContextAwareProcessor,实现spring容器中某一个类的bean对象在初始化时需要得到Spring容器内容。


    需求:我们的需求是,在spring初始化完毕时,使我们自定义一个类Bird类可以得到spring容器内容。

    实现步骤:

    1.首先我们来看一下ApplicationContextAwareProcessor这个类,它是BeanPostProcessor(后置处理器)的一个实现类。所以ApplicationContextAwareProcessor里面也必定有后置处理器接口的两个前置和后置方法。

    我们来看一下ApplicationContextAwareProcessor的前置方法:由前面讲解的后置处理器(链接:https://www.cnblogs.com/WNof11020520/p/10598745.html)可知,所有bean对象初始化前都会执行BeanPostProcessor接口实现类的前置方法postProcessBeforeInitialization,所以所有bean对象初始化前都会执行ApplicationContextAwareProcessor的postProcessBeforeInitialization方法。

     1 @Nullable
     2     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
     3         AccessControlContext acc = null;
     4         if(System.getSecurityManager() != null && (bean instanceof EnvironmentAware || 
     5                                                     bean instanceof EmbeddedValueResolverAware || 
     6                                                     bean instanceof ResourceLoaderAware || 
     7                                                     bean instanceof ApplicationEventPublisherAware || 
     8                                                     bean instanceof MessageSourceAware || 
     9                                                     bean instanceof ApplicationContextAware)) {
    10             acc = this.applicationContext.getBeanFactory().getAccessControlContext();
    11         }
    12 
    13         if(acc != null) {
    14             AccessController.doPrivileged(() -> {
    15                 this.invokeAwareInterfaces(bean);
    16                 return null;
    17             }, acc);
    18         } else {
    19             this.invokeAwareInterfaces(bean);
    20         }
    21 
    22         return bean;
    23     }
    24 
    25     private void invokeAwareInterfaces(Object bean) {
    26         if(bean instanceof Aware) {
    27             if(bean instanceof EnvironmentAware) {
    28                 ((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment());
    29             }
    30 
    31             if(bean instanceof EmbeddedValueResolverAware) {
    32                 ((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(this.embeddedValueResolver);
    33             }
    34 
    35             if(bean instanceof ResourceLoaderAware) {
    36                 ((ResourceLoaderAware)bean).setResourceLoader(this.applicationContext);
    37             }
    38 
    39             if(bean instanceof ApplicationEventPublisherAware) {
    40                 ((ApplicationEventPublisherAware)bean).setApplicationEventPublisher(this.applicationContext);
    41             }
    42 
    43             if(bean instanceof MessageSourceAware) {
    44                 ((MessageSourceAware)bean).setMessageSource(this.applicationContext);
    45             }
    46 
    47             if(bean instanceof ApplicationContextAware) {
    48                 ((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
    49             }
    50         }
    51 
    52     }

    2.看以上代码第9、15、19、48行可知,假若bean对象的类是ApplicationContextAware类型的话,就会调用invokeAwareInterfaces方法,然后执行第48行,将spring容器赋值给bean对象的applicationContext属性。

    所以重要的实现思路来了:

      a.Bird类实现ApplicationContextAware接口,并添加一个ApplicationContext类型的属性context,并实现ApplicationContextAware接口的方法:

     1 @Component
     2 public class Bird implements ApplicationContextAware {
     3     //得到管理它的Spring容器
     4     private ApplicationContext context;
     5 
     6     @Override
     7     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
     8         this.context = applicationContext;
     9     }
    10 
    11     @Override
    12     public String toString() {
    13         return "Bird [context=" + context + "]";
    14     }
    15 }

      b.写一个测试类,测试结果:

     1 public class TestMain {
     2 
     3     public static void main(String[] args) {
     4         // 1.获得Spring容器对象
     5         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
     6         System.out.println("Spring容器 " + context);
     7         Bird bird = (Bird) context.getBean("bird");
     8         System.out.println(bird);
     9     }
    10 }

      c.查看测试输出的结果:输出结果显示,TestMain 类的main方法中new出来的context和Bird组件的bean对象的context属性地址相同,所以Bird的bean对象得到了spring容器内容。

    1 "C:Program FilesJavajdk1.8.0_25injava" -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:52099,suspend=y,server=n -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_25jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_25jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_25jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_25jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_25jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_25jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_25jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_25jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_25jrelibext
    ashorn.jar;C:Program FilesJavajdk1.8.0_25jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_25jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_25jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_25jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_25jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_25jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_25jrelibjce.jar;C:Program FilesJavajdk1.8.0_25jrelibjfr.jar;C:Program FilesJavajdk1.8.0_25jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_25jrelibjsse.jar;C:Program FilesJavajdk1.8.0_25jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_25jrelibplugin.jar;C:Program FilesJavajdk1.8.0_25jrelib
    esources.jar;C:Program FilesJavajdk1.8.0_25jrelib
    t.jar;D:kaikeba_java2018-11-28-spring-beanpostprocessor2-项目11_Spring_BeanPostProcessor的实现类介绍	arget	est-classes;D:kaikeba_java2018-11-28-spring-beanpostprocessor2-项目11_Spring_BeanPostProcessor的实现类介绍	argetclasses;D:caowenlongjavaDevelopToolapache-maven-3.5.3-bin
    epoorgspringframeworkspring-context5.0.5.RELEASEspring-context-5.0.5.RELEASE.jar;D:caowenlongjavaDevelopToolapache-maven-3.5.3-bin
    epoorgspringframeworkspring-aop5.0.5.RELEASEspring-aop-5.0.5.RELEASE.jar;D:caowenlongjavaDevelopToolapache-maven-3.5.3-bin
    epoorgspringframeworkspring-beans5.0.5.RELEASEspring-beans-5.0.5.RELEASE.jar;D:caowenlongjavaDevelopToolapache-maven-3.5.3-bin
    epoorgspringframeworkspring-core5.0.5.RELEASEspring-core-5.0.5.RELEASE.jar;D:caowenlongjavaDevelopToolapache-maven-3.5.3-bin
    epoorgspringframeworkspring-jcl5.0.5.RELEASEspring-jcl-5.0.5.RELEASE.jar;D:caowenlongjavaDevelopToolapache-maven-3.5.3-bin
    epoorgspringframeworkspring-expression5.0.5.RELEASEspring-expression-5.0.5.RELEASE.jar;D:caowenlongjavaDevelopToolIntelliJ IDEA 2016.2libidea_rt.jar" com.kkb.test.TestMain
    2 Connected to the target VM, address: '127.0.0.1:52099', transport: 'socket'
    3 三月 26, 2019 11:26:26 上午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
    4 信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2ed94a8b: startup date [Tue Mar 26 11:26:26 CST 2019]; root of context hierarchy
    5 Spring容器 org.springframework.context.annotation.AnnotationConfigApplicationContext@2ed94a8b: startup date [Tue Mar 26 11:26:26 CST 2019]; root of context hierarchy
    6 Bird [context=org.springframework.context.annotation.AnnotationConfigApplicationContext@2ed94a8b: startup date [Tue Mar 26 11:26:26 CST 2019]; root of context hierarchy]
    7 Disconnected from the target VM, address: '127.0.0.1:52099', transport: 'socket'
    8 
    9 Process finished with exit code 0
  • 相关阅读:
    DataImport(译)
    Spring JDBC最佳实践(1)
    在Spring中快速使用EHCache注解
    VS 2010 WPF核心是哪些功能特性 ?
    [你必须知道的.NET]第十五回:继承本质论
    C#设置本地网络(DNS、网关、子网掩码、IP)
    [你必须知道的.NET]第十六回:深入浅出关键字using全接触
    逆变与协变
    C# 判断网站是否能访问或者断链
    接口与抽象类
  • 原文地址:https://www.cnblogs.com/WNof11020520/p/10599073.html
Copyright © 2020-2023  润新知