• Spring的bean创建过程分析之resolveBeforeInstantiation的调用执行


    Spring的bean创建过程分析之resolveBeforeInstantiation的调用执行

    我们接着上面的Bean 的创建流程,今天来谈谈 resolveBeforeInstantiation 的调用执行。

    此方法存在的意义在于给BeanPostProcessor的实现子类一个机会去生成代理对象来替代对象。

    顾名思义, 我们需要生成的对象是一个代理对象。 这样也可以创建bean。

    1、案例实现

    • BeforeInstantiation.java
    package com.qzk.QzkResolveBeforeInstantiation;
    
    /**
     * @ClassName BeforeInstantiation
     * @Description 创建一个 BeforeInstantiation 的一个类, 该类只有一个方法, do some things
     * @Author qzk
     * @Date 2022/4/26 11:43 下午
     * @Version 1.0
     **/
    public class BeforeInstantiation {
    
        public void doSomething(){
            System.out.println(" 执行do some thing ...");
        }
    }
    
    • QzkMethodInterceptor.java
    package com.qzk.QzkResolveBeforeInstantiation;
    
    import org.aopalliance.intercept.MethodInvocation;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    /**
     *
     * @ClassName QzkMethodInterceptor
     * @Description 拦截器
     * @Author qzk
     * @Date 2022/4/26 11:52 下午
     * @Version 1.0
     **/
    public class QzkMethodInterceptor implements MethodInterceptor {
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("目标方法执行之前: " + method);
            Object o1 = methodProxy.invokeSuper(o, objects);
            System.out.println("目标方法执行之后: " + method);
            return o1;
        }
    }
    
    
    package com.qzk.QzkResolveBeforeInstantiation;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.PropertyValues;
    import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
    import org.springframework.cglib.proxy.Enhancer;
    
    /**
     * @ClassName QzkInstantiationAwareBeanPostProcessor
     * @Description
     * @Author qzk
     * @Date 2022/4/26 11:45 下午
     * @Version 1.0
     **/
    public class QzkInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    
    
        /**
         * 实例化之前的操作
         *
         * @param beanClass the class of the bean to be instantiated
         * @param beanName  the name of the bean
         * @return
         * @throws BeansException
         */
        @Override
        public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    
    //        if (beanClass.equals(BeforeInstantiation.class)) {
                System.out.println("当前beanName:" + beanName + "--> 执行:postProcessBeforeInstantiation 实例化之前");
                if (beanClass == BeforeInstantiation.class) {
                    // 创建动态代理类的增强类
                    Enhancer enhancer = new Enhancer();
                    //  设置类加载器
                    enhancer.setClassLoader(beanClass.getClassLoader());
                    //  设置被动态代理类所代理的 被代理类
                    enhancer.setSuperclass(beanClass);
                    // 设置方法拦截器
                    enhancer.setCallback(new QzkMethodInterceptor());
                    //  创建代理类
                    BeforeInstantiation beforeInstantiation = (BeforeInstantiation) enhancer.create();
                    System.out.println("创建代理对象:" + beforeInstantiation);
                    return beforeInstantiation;
                }
                return nulll;
        }
    
        /**
         * 实例化之后的操作
         *
         * @param bean     the bean instance created, with properties not having been set yet
         * @param beanName the name of the bean
         * @return
         * @throws BeansException
         */
        @Override
        public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
            System.out.println("当前beanName:" + beanName + "--> 执行:postProcessAfterInstantiation 实例化之后");
            return false;
        }
    
        /**
         * 对当前属性值的一个相关处理工作
         *
         * @param pvs      the property values that the factory is about to apply (never {@code null})
         * @param bean     the bean instance created, but whose properties have not yet been set
         * @param beanName the name of the bean
         * @return
         * @throws BeansException
         */
        @Override
        public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
            System.out.println("当前beanName:" + beanName + "--> 执行:postProcessProperties 属性值的处理");
            return pvs;
        }
    
        /**
         * 初始化之前的做哪些操作
         *
         * @param bean     the new bean instance
         * @param beanName the name of the bean
         * @return
         * @throws BeansException
         */
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("当前beanName:" + beanName + "--> 执行:postProcessBeforeInitialization 初始化之前");
    
            return bean;
        }
    
        /**
         * 初始化之后做哪些操作
         *
         * @param bean     the new bean instance
         * @param beanName the name of the bean
         * @return
         * @throws BeansException
         */
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("当前beanName:" + beanName + "--> 执行:postProcessAfterInitialization 初始化之后");
            return bean;
        }
    }
    
    
    • 测试类
    package com.qzk.QzkResolveBeforeInstantiation;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * @ClassName QzkTest
     * @Description TODO
     * @Author qzk
     * @Date 2022/4/27 12:01 上午
     * @Version 1.0
     **/
    public class QzkTest {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("QzkResolveBeforeInstantiation.xml");
            BeforeInstantiation bean = context.getBean(BeforeInstantiation.class);
            bean.doSomething();
        }
    }
    
    
    • xml配置文件
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="beforeInstantiation" class="com.qzk.QzkResolveBeforeInstantiation.BeforeInstantiation"></bean>
        <bean id="myInstantiationAwareBeanPostProcessor" class="com.qzk.QzkResolveBeforeInstantiation.QzkInstantiationAwareBeanPostProcessor"></bean>
    
    </beans>
    

    在上面的代码中,我们看到有一个类 是实现了InstantiationAwareBeanPostProcessor 接口的,针对这个接口,我们可以先看一下他的一个类图的继承关系。

    image-20220511112055917

    image-20220511112129120

    image-20220511112232916

    根据上图所示, 因此, QzkInstantiationAwareBeanPostProcessor在实现 InstantiationAwareBeanPostProcessor 接口之后,是属于 BeanPostProcessor的,因此在refresh() 的流程中, 是通过registerBeanPostProcessors(beanFactory) 方式, 实现的一个BPP的创建的。

    image-20220511114439436

    image-20220511114724401

    当我们执行 finishBeanFactoryInitialization(beanFactory) 的时候, 里面继续执行到 preInstantiateSingletons

    image-20220511115156851

    紧接着就是执行我们的getBean --> doGetBean --> createBean ---> doCreateBean 的一个流程, 这里不做过多的赘述。

    在具体的执行过程中, 我们自定义的 beforeInstatiation 此时会走下面的逻辑

    ![image-20220511132013946](/Users/qzk/Library/Application Support/typora-user-images/image-20220511132013946.png)

    ![image-20220511132209559](/Users/qzk/Library/Application Support/typora-user-images/image-20220511132209559.png)

    ![image-20220511132307893](/Users/qzk/Library/Application Support/typora-user-images/image-20220511132307893.png)

    ![image-20220511132451405](/Users/qzk/Library/Application Support/typora-user-images/image-20220511132451405.png)

    当第二次for BeanName 循环的时候, 是获取 Qzk... ,此时执行到如下图的doGetBean 方法的时候,因为可以从缓存中获取到这个BPP,所以是通过 getObjetcForBeanInstance 方法来获取bean 的。

    image-20220511133725933

    image-20220511134454958

    image-20220511134537873

    上图就是通过拦截器来进行执行的操作结果。

    总结:

    • Spring 中bean的创建, 还可以通过 实现了 InstantiationAwarePostProcessor 接口的类 , 并结合动态代理去实现创建我们所需要的动态代理对象。
    • 这个过程是通过 resolveBeforeInstantiation 方法区调用执行的,并生成代理对象的。
  • 相关阅读:
    原生JS中Ajax的使用方法
    back-to-top回到顶部
    atom插件
    git 命令操作
    常用font-family
    上传按钮美化
    mongodb
    GraphicsMagick命令
    enctype=“multipart/form-data”详解
    操作符
  • 原文地址:https://www.cnblogs.com/qianzhengkai/p/16257639.html
Copyright © 2020-2023  润新知