今天看啥  ›  专栏  ›  涣涣虚心0215

Spring IOC(2)BeanDefinition

涣涣虚心0215  · 简书  ·  · 2020-12-07 19:13

文章预览

在开始源码分析之前,share一下Spring IOC的流程图:【 Spring IOC(1)流程图
Spring通过BeanDefinition将配置文件中的<bean>配置信息转换为容器的内部表示,并将这些BeanDefiniton注册到BeanDefinitonRegistry中。Spring容器的BeanDefinitionRegistry就像是Spring配置信息的内存数据库,主要是以map的形式保存,后续操作直接从BeanDefinitionRegistry中读取配置信息( DefaultListableBeanFactory是实现类,内部通过beanDefinitionMap保存BeanDefinition )。
比如上一篇文章的代码,通过ClassPathResource读取配置文件,然后通过BeanDefinitionReader将BeanDefinition加载并注册到DefaultListableBeanFactory中。

ClassPathResource classPathResource = new ClassPathResource("applicationContext.xml");
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions(classPathResource);

Student student = (Student) beanFactory.getBean("student");
System.out.println(student.getName());

同样在ApplicationContext中也是这样的逻辑:
loadBeanDefinitions则是通过模板方法模式,由子类实现是从xml还是通过Annotation获取BeanDefinition,不过大体逻辑还是一样,通过BeanDefinitionReader关联BeanFactory和读取的BeanDefinition。

在refresh()方法中,通过obtainFreshBeanFactory获得BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    return getBeanFactory();
}
//这里真正的创建BeanFactory,并且加载BeanDefinition
protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        //创建BeanFactory
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory);
        //加载BeanDefinition
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing 
                    bean definition source for " + getDisplayName(), ex);
    }
}
//AbstractXmlApplicationContext实现的loadBeanDefinitions,从xml中读取BeanDefinition
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, 
IOException {
    // Create a new XmlBeanDefinitionReader for the given BeanFactory.
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    initBeanDefinitionReader(beanDefinitionReader);
    loadBeanDefinitions(beanDefinitionReader);
}
BeanDefinition

BeanDefinition是一个接口类型,提供以下功能:

  • bean的描述信息(Scope单例还是原型bean,Lazy懒加载,是不是抽象abstract)
  • 依赖类类名(String[] dependOn)
  • 自动装配的相关信息(AutowireCandidate,Primary)
  • init函数,destroy函数的名字(String类型)
  • factoryBean的名字以及FactoryMethod
  • 构造函数形参的值(ConstructorArgumentValues)
  • Bean的属性以及对应的值(MutablePropertyValues)
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    //单例模式
    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
    //原型模式
    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
    //返回当前BeanDefinition的Parent Definition
    String getParentName();
    //设置当前BeanDefinition所属class name
    void setBeanClassName(@Nullable String beanClassName);
    //获得bean所属class name
    String getBeanClassName();
    //设置Scope是单例还是原型
    void setScope(@Nullable String scope);
    //获取Scope
    String getScope();
    //设置bean是否被懒加载
    void setLazyInit(boolean lazyInit);
    //判断bean是否是懒加载
    boolean isLazyInit();
    //设置bean初始化时depend on的bean的name
    void setDependsOn(@Nullable String... dependsOn);
    //获取这个bean所depend on的bean数组
    String[] getDependsOn();
    //设置当前bean是不是一个被Autowired到别的bean的候选bean
    void setAutowireCandidate(boolean autowireCandidate);
    //查看这个bean是不是Autowired到别的bean的候选bean
    boolean isAutowireCandidate();
    // 设置这个bean是primary autowire candidate
    void setPrimary(boolean primary);
    //这个bean是不是primary autowire candidate
    boolean isPrimary();
    //如果需要FactoryBean的话,指定FactoryBean的名字
    void setFactoryBeanName(@Nullable String factoryBeanName);
    //获取Factorybean的名字
    String getFactoryBeanName();
    //设置FactoryMethod,可以被factoryBean使用
    void setFactoryMethodName(@Nullable String factoryMethodName);
    //获取FactoryMethod
    String getFactoryMethodName();
    //返回构造函数参数
    ConstructorArgumentValues getConstructorArgumentValues();
    //是否有构造函数参数
    default boolean hasConstructorArgumentValues() {
        return !getConstructorArgumentValues().isEmpty();
    }
    //返回property相关值
    MutablePropertyValues getPropertyValues();
    //是否有property值定义
    default boolean hasPropertyValues() {
        return !getPropertyValues().isEmpty();
    }
    //设置initializer method
    void setInitMethodName(@Nullable String initMethodName);
    //返回initializer method
    String getInitMethodName();
    //设置destroy method
    void setDestroyMethodName(@Nullable String destroyMethodName);
    //获取destroy method
    String getDestroyMethodName();
    //设置role
    void setRole(int role);
    //获取role
    int getRole();
    //设置description
    void setDescription(@Nullable String description);
    //获取description
    String getDescription();


    // Read-only attributes
    //判断是不是单例bean
    boolean isSingleton();
    //判断是不是原型bean
    boolean isPrototype();
    //判断bean是不是abstract的
    boolean isAbstract();
    //获取资源的description
    String getResourceDescription();
    //获取originating BeanDefinition
    BeanDefinition getOriginatingBeanDefinition();
}

针对于该接口,提供了AbstractBeanDefinition这样一个抽象类,在该类中提供了上述set方法所对应的变量,以及实现。


private volatile Object beanClass;
private String scope = SCOPE_DEFAULT;
private boolean abstractFlag = false;
private boolean lazyInit = false;
private int autowireMode = AUTOWIRE_NO;
private int dependencyCheck = DEPENDENCY_CHECK_NONE;
private String[] dependsOn;
private boolean autowireCandidate = true;
private boolean primary = false;
private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>();
private Supplier<?> instanceSupplier;
private boolean nonPublicAccessAllowed = true;
private boolean lenientConstructorResolution = true;
private String factoryBeanName;
private String factoryMethodName;
private ConstructorArgumentValues constructorArgumentValues;
private MutablePropertyValues propertyValues;
private MethodOverrides methodOverrides;
private String initMethodName;
private String destroyMethodName;
private boolean enforceInitMethod = true;
private boolean enforceDestroyMethod = true;
private boolean synthetic = false;
private int role = BeanDefinition.ROLE_APPLICATION;
@Nullable
private String description;
@Nullable
private Resource resource;

那么最终实现类RootBeanDefinition是比较常用的一种,内部提供了BeanDefinitionHolder来保存BeanDefinition和beanName。

BeanDefinition实例

因为XML比较直观,所以这里主要通过XML的形式配置bean,后面再整理基于Annotation方式的。


image.png

从上图可以看出<bean>标签内可以定义这些内容,最终都会解析到BeanDefinition的属性中。


image.png
运行时修改BeanDefinition定义

一般情况下,BeanDefinition只在容器启动时加载并解析,除非容器刷新或重启,这些信息不会发生变化,当然如果用户有特殊的需求,也可以通过编程的方式在运行期调整BeanDefinition的定义。

public class BeanDefinitionPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        BeanDefinition student = registry.getBeanDefinition("student");
        student.getPropertyValues().getPropertyValue("name").setConvertedValue("Test");
    }
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        BeanDefinition student = beanFactory.getBeanDefinition("student");
        student.getPropertyValues().getPropertyValue("name").setConvertedValue("Test1");
        //通过转换成DefaultListableBeanFactory来registerBeanDefinition
        ((DefaultListableBeanFactory) beanFactory).registerBeanDefinition("test" ,student);
    }
}

如上述代码,BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor,所以它会有两个方法,如果只是获取BeanDefinition并更新,那么BeanFactoryPostProcessor也能够操作, 且BeanFactoryPostProcessor还提供注册新的BeanDefinition,但是需要将ConfigurableListableBeanFactory强制转换成DefaultListableBeanFactory。
在AbstractApplicationContext中,提供了addBeanFactoryPostProcessor(new BeanDefinitionPostProcessor());且在refresh()方法里会通过invokeBeanFactoryPostProcessors(beanFactory)来调用BeanFactoryPostProcessor。

………………………………

原文地址:访问原文地址
快照地址: 访问文章快照
总结与预览地址:访问总结与预览