SpringBoot中Bean的创建过程及扩展操作点 @by_TWJ

1. 类含义

  • BeanDefinition - 类定义,为Bean创建提供一些定义类的信息。实现类如下:
    • RootBeanDefinition - 类定义信息,包含有父子关系的BeanDefinition。是常用的实例化BeanDefinition。
  • BeanWrapper - 封装Bean,包含有实例化的Bean、Bean类、属性描述集合。一般用来做属性注入。实现类如下:
    • BeanWrapperImpl
  • AbstractApplicationContext - 应用上下文,实现类如下:
    • AnnotationConfigWebApplicationContext - 使用注解的方式配置Web应用上下文(常用)
    • AnnotationConfigReactiveWebApplicationContext - 使用注解的方式配置ReactiveWeb应用上下文
    • FileSystemXmlApplicationContext - 通过本地系统查找XML配置文件来启动的 应用上下文。(略)
    • ClassPathXmlApplicationContext- 通过编译路径查找XML配置文件来启动的 应用上下文。(略)
    • XmlWebApplicationContext- 通过XML配置文件来启动的 Web应用上下文。(略)
    • GenericXmlApplicationContext- 通过XML配置文件配置 应用上下文。(略)
    • StaticWebApplicationContext- 静态web服务的应用上下文。(略)
  • BeanFactory - Bean工厂,负责提供Bean
  • BeanDefinitionRegistry - BeanDefinition的注册表,用来放置BeanDefinition。
  • BeanUtils - 里面有很多Bean操作,例如:使用无参构造函数创建Bean:BeanUtils.instantiateClass(beanClass)
  • ConstructorResolver - 构造函数解析器,用来注入有参的构造函数。有参是一个Bean类,就会从BeanFactory获取该Bean。
  • MutablePropertyValues - 可变的属性值,用来装载属性名称还有属性值。有点类似Map,但它比Map包含有更多的属性定义信息。一般使用beanWrapper.setPropertyValues(mutablePropertyValues),直接把可变的属性值,注入到Bean中。
  • *PostProcessor - 后置处理程序,用于操作的前后事件等。

2. Bean创建过程 - 流程图

忽略了很多中间的判定操作。
这里只记录扩展点,方便以后做扩展。

在这里插入图片描述

3. 例子

3.1. 可变属性注入到实体中

package org.springframework.beans.factory.support;

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.MutablePropertyValues;

public class MutablePropertyValuesTest {
    // 可变属性注入到实体中。
    public static void main(String[] args) {
        MutablePropertyValues mutablePropertyValues  = new MutablePropertyValues();
        mutablePropertyValues.addPropertyValue("name", "tavion");
        mutablePropertyValues.addPropertyValue("age", 1);
        BeanWrapper beanWrapper = new BeanWrapperImpl(PropertyBean.class);
        beanWrapper.setPropertyValues(mutablePropertyValues);
        System.out.println(beanWrapper.getPropertyValue("name"));//输出:tavion
        System.out.println(((PropertyBean)beanWrapper.getWrappedInstance()).getName());//输出:tavion
        System.out.println(beanWrapper.getPropertyValue("age"));//输出:1
        System.out.println(((PropertyBean)beanWrapper.getWrappedInstance()).getAge());//输出:1
    }
}
class PropertyBean{
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

3.2. 模拟Bean创建的例子



import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.util.ClassUtils;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

@Slf4j
public class BeanCreateTest {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

        // 0. 参数初始化
        Object bean = null;//实例化后的Bean

        Class<?> beanClass = BeanTest1.class;//要实例化的Bean类
        String beanName = ClassUtils.getShortName(beanClass);//要实例化的Bean名称


        // 1. 创建Context 上下文和BeanFactory
        AbstractApplicationContext context = new GenericApplicationContext();
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory();

        // 2. 配置TestUser和TestOrg的BeanDefinition
        RootBeanDefinition mbd = new RootBeanDefinition(beanClass);
        beanFactory.registerBeanDefinition(BeanTest2.class.getName(),new RootBeanDefinition(BeanTest2.class));
        beanFactory.registerBeanDefinition(beanName,mbd);

        // 3. 注册 BeanPostProcessor
        registerAutowiredAnnotationBeanPostProcessor(context);

        // 4. 检索构造方法,通过有参构造方法创建Bean
        // tip:这里我只是把beanFactory.getBean()里面的操作,简写重复写一遍。
        for (SmartInstantiationAwareBeanPostProcessor beanPostProcessor : beanFactory.getBeanPostProcessorCache().smartInstantiationAware) {
//            AutowiredAnnotationBeanPostProcessor beanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
            Constructor<?>[] ctors = beanPostProcessor.determineCandidateConstructors(beanClass, beanName);
            if (ctors != null) {
                log.info("1. 通过构造方法的方式创建Bean:"+beanName);
                // 得到构造参数,注入属性,若是Bean类,则会通过beanFactory.getBean() 方式得到传参值。getBean如果没有,则创建新的Bean
                BeanWrapper beanWrapper = new ConstructorResolver(beanFactory)
                        .autowireConstructor(beanName, mbd, ctors, null);
                bean = beanWrapper.getWrappedInstance();
                if(bean!=null){
                    break;
                }

            }
        }
        // 5. 通过无参构造方法创建Bean
        if(bean==null){
            log.info("2. 通过无构造方法的方式创建Bean");
            bean = BeanUtils.instantiateClass(beanClass);
        }

        // 6. 打印实例化后的Bean
        System.out.println(bean);
    }

    private static void registerAutowiredAnnotationBeanPostProcessor(AbstractApplicationContext context) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)context.getBeanFactory();
        // 1. 加入 AutowiredAnnotationBeanPostProcessor 后置处理器
        beanFactory.registerBeanDefinition(AutowiredAnnotationBeanPostProcessor.class.getName(),
                new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class));

        // 2. AutowiredAnnotationBeanPostProcessor 加入到缓存中,待后续执行
//        2.1. context.invokeBeanFactoryPostProcessors(beanFactory);// 因为是protected修饰的方法,所以我们在这里需要用反射方式调用
        Method method = AbstractApplicationContext.class.getDeclaredMethod("invokeBeanFactoryPostProcessors", ConfigurableListableBeanFactory.class);
        method.setAccessible(true);
        method.invoke(context, beanFactory);
//        2.2。 context.registerBeanPostProcessors(beanFactory);// 因为是protected修饰的方法,所以我们在这里需要用反射方式调用
        Method method2 = AbstractApplicationContext.class.getDeclaredMethod("registerBeanPostProcessors", ConfigurableListableBeanFactory.class);
        method2.setAccessible(true);
        method2.invoke(context, beanFactory);
    }

}
class BeanTest1 {


    private BeanTest2 beanTest2;

    public BeanTest1(BeanTest2 beanTest2) {
        this.beanTest2 = beanTest2;
    }

}
class BeanTest2 {

}




  • 19
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值