zoukankan      html  css  js  c++  java
  • BeanPostProcessor原理--使用讲解

    《Spring源码解析》笔记

    BeanPostProcessor原理学习

    在学习BeanPostProcessor的原理学习完之后,对Spring如何使用充满好奇,尝试使用例子进行理解,以下记录过程:

    1、使用ApplicationContextAware,可以指定,在当前函数中获取到容器上下文,具体使用举例如下:

    @Component
    public class Dog implements ApplicationContextAware {
    
        //@Autowired
        private ApplicationContext context;
    
        public Dog(){
            System.out.println("dog constructor...");
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            // TODO Auto-generated method stub
            this.context = applicationContext; } }

    2、在Dog类中通过使用变量context即可获取Spring的容器上下文,但是具体如何实现?

         ApplicationContextAware本身并没有继承BeanPostProcess,只继承Aware接口 

    public interface ApplicationContextAware extends Aware {
    
        /**
         * Set the ApplicationContext that this object runs in.
         * Normally this call will be used to initialize the object.
         * <p>Invoked after population of normal bean properties but before an init callback such
         * as {@link org.springframework.beans.factory.InitializingBean#afterPropertiesSet()}
         * or a custom init-method. Invoked after {@link ResourceLoaderAware#setResourceLoader},
         * {@link ApplicationEventPublisherAware#setApplicationEventPublisher} and
         * {@link MessageSourceAware}, if applicable.
         * @param applicationContext the ApplicationContext object to be used by this object
         * @throws ApplicationContextException in case of context initialization errors
         * @throws BeansException if thrown by application context methods
         * @see org.springframework.beans.factory.BeanInitializationException
         */
        void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
    
    }

      通过代码运行,可以看到调用,该setApplicationContext是通过类ApplicationContextAwareProcessor实现,

      查看ApplicationContextAwareProcessor:

    class ApplicationContextAwareProcessor implements BeanPostProcessor {}

    当容器中的Bean赋值后,会遍历容器中的BeanPostProcessor ,挨个执行,自然会执行到ApplicationContextAwareProcessor 的postProcessBeforeInitialization()方法。

    在其中执行的是this.invokeAwareInterfaces(bean)函数,查看invokeAwareInterfaces()函数代码:

    private void invokeAwareInterfaces(Object bean) {
            if (bean instanceof Aware) {
                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 ApplicationContextAware) {
                    ((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
                }
            }
    
        }

    3、从代码中可以看出

         该函数只会执行实现Aware接口的Bean,我们的实现类Dog实现的是ApplicationContextAware

        即会执行其相关的代码,自动为Dog中变量进行赋值。

    4、引申学习Aware 

         自定义组件实现xxxAware;在创建对象的时候,会调用接口规定的方法注入相关组件;Aware;

         把Spring底层一些组件注入到自定义的Bean中; 

        xxxAware:部分Aware接口的功能使用xxxProcessor;

      ApplicationContextAware==》ApplicationContextAwareProcessor;

      例如BeanNameAware接口的实现见4.3;

      4.1 Aware的子接口如图所示:

       

      4.2 举例Aware的使用方式

      

    @Component
    public class Red implements ApplicationContextAware,BeanNameAware,EmbeddedValueResolverAware {
        private ApplicationContext applicationContext;
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            // TODO Auto-generated method stub
            System.out.println("传入的ioc:"+applicationContext);
            this.applicationContext = applicationContext;
        }
        @Override
        public void setBeanName(String name) {
            // TODO Auto-generated method stub
            System.out.println("当前bean的名字:"+name);
        }
        //StringValueResolver:Resolve the given String value, for example parsing placeholders.
        @Override
        public void setEmbeddedValueResolver(StringValueResolver resolver) {
            // TODO Auto-generated method stub
            String resolveStringValue = resolver.resolveStringValue("你好 ${os.name} 我是 #{20*18}");
            System.out.println("解析的字符串:"+resolveStringValue);
        }
    }

       4.2 BeanNameAware接口的实现

      首先在函数initializeBean中,会调用invokeAwareMethods函数,其中Beanpostprocess的两个方法及初始化方法都是在该函数中进行执行。

       进入invokeAwareMethods函数

       

      在函数中可以观察到部分Aware的子接口均是在此实现。

  • 相关阅读:
    自我介绍 x
    第一次作业 x
    第二次作业 x
    第三次作业 x
    [C#] 用一种更优美的方式来替换掉又多又长的switchcase代码段
    通过设置光标形状实现拖拽控件时跟随一张透明图片的效果
    spring 入门笔记(一)
    PAT IO01. 表格输出(5)
    Maven 安装记
    华为机试 求最大三位数
  • 原文地址:https://www.cnblogs.com/mayang2465/p/12098434.html
Copyright © 2011-2022 走看看