ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-05-11 14:03:32  阅读:637  来源: 互联网

标签:Object return resolveBeforeInstantiation Spring beanName bean qzk public


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 方法区调用执行的,并生成代理对象的。

标签:Object,return,resolveBeforeInstantiation,Spring,beanName,bean,qzk,public
来源: https://www.cnblogs.com/qianzhengkai/p/16257639.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有