Spring 学习笔记-BeanDefinition

BeanDefinition

BeanDefinition 是用来描述创建 Bean 的信息,包括 Bean 的 class ,属性填充,是否懒加载等信息。
BeanDefinition 跟 Bean 的关系,就好像是类与对象的关系,Bean 的创建依赖 BeanDefinition。

BeanDefinition 的源码如下:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    // singleton 类型 Bean 的标志
    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
    // prototype 类型 Bean 的标志
    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

    // BeanDefinition 的角色信息,表示是通过用户创建的 bean
    int ROLE_APPLICATION = 0;
    // BeanDefinition 的角色信息,表示该 Bean 用于支撑某些配置信息
    int ROLE_SUPPORT = 1;
    // BeanDefinition 的角色信息,表示该 bean 用于支撑一些 Spring 内部运作
    int ROLE_INFRASTRUCTURE = 2;
    
    /**
    * bean 的 parentName 的 setter 和 getter 方法
    * parentName 表示 Bean 的父级名字
    */
    void setParentName(@Nullable String parentName);
    String getParentName();

    // BeanClassName 的 setter 跟 getter 方法
    void setBeanClassName(@Nullable String beanClassName);
    String getBeanClassName();

    /**
    * scope 的 setter 跟 getter 方法
    * scope 表示这个 Bean 的类型,是 singleton 还是 prototype 类型
    */
    void setScope(@Nullable String scope);
    String getScope();

    /**
    * lazyInit 的 setter 跟 getter 方法
    * lazyInit 表示是否懒加载 Bean
    */
    void setLazyInit(boolean lazyInit);
    boolean isLazyInit();

    // dependsOn 的 setter 跟 getter 方法
    void setDependsOn(@Nullable String... dependsOn);
    String[] getDependsOn();

    // autowireCandidate 的 setter 跟 getter 方法
    void setAutowireCandidate(boolean autowireCandidate);
    boolean isAutowireCandidate();

    // primary 的 setter 跟 getter 方法
    void setPrimary(boolean primary);
    boolean isPrimary();

    // fatoryBeanName 的 setter 跟 getter 方法
    void setFactoryBeanName(@Nullable String factoryBeanName);
    String getFactoryBeanName();

    // factoryMethodName 的 setter 跟 getter 方法
    void setFactoryMethodName(@Nullable String factoryMethodName);
    String getFactoryMethodName();

    // 获取 ConstructorArgumentValues 的值
    ConstructorArgumentValues getConstructorArgumentValues();
    // 判断是否有 ConstructorArgumentValues
    default boolean hasConstructorArgumentValues() {
        return !getConstructorArgumentValues().isEmpty();
    }

    // 获取 PropertyValues
    MutablePropertyValues getPropertyValues();
    // 判断 PropertyValues 是否为空
    default boolean hasPropertyValues() {
        return !getPropertyValues().isEmpty();
    }

    // initMthodName 的 getter 跟 setter 方法
    void setInitMethodName(@Nullable String initMethodName);
    String getInitMethodName();

    // destroyMethodName 的 getter 跟 setter 方法
    void setDestroyMethodName(@Nullable String destroyMethodName);
    String getDestroyMethodName();

    // bean 角色的 setter 跟 getter 方法
    void setRole(int role);
    int getRole();

    /**
    * description 的 getter 和 setter 方法
    * description 表示 bean 的描述信息
    */
    void setDescription(@Nullable String description);
    String getDescription();

    // 返回 Bean 的 ResolvableType
    ResolvableType getResolvableType();

    // 是否为 singleton 类型的 bean
    boolean isSingleton();

    // 是否为 prototype 类型的 bean
    boolean isPrototype();

    // 是否为抽象类,如果是则表示这个 bean 无法初始化
    boolean isAbstract();

    // 获取资源描述信息
    String getResourceDescription();

    // 获取被包装的 BeanDefinition,如果这个 BeanDefinition 是包装类,那么就会返回被包装的原始类 
    BeanDefinition getOriginatingBeanDefinition();

}

BeanDefinition 的常用子类

  • AbstractBeanDefinition
  • RootBeanDefinition
  • ChildBeanDefinition
  • GenericBeanDefinition
  • AnnotatedGenericBeanDefinition

AbstractBeanDefinition

BeanDefinition 的抽象实现类,对于 BeanDefinition 的大部分接口提供了关联的字段。

RootBeanDefinition

AbstractBeanDefinition 的实现类之一,是常用的 BeanDefinition

用法

public static class User {
    protected String username;
    protected String address;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

@Test
void rbdTest() {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
    MutablePropertyValues mpv = new MutablePropertyValues();
    mpv.add("username", "yosoro");
    mpv.add("address", "cn");
    RootBeanDefinition rbd = new RootBeanDefinition(User.class, null, mpv);
    ctx.registerBeanDefinition("user", rbd);
}

输出结果

User{username='yosoro', address='cn'}

ChildBeanDefinition

AbstractBeanDefinition 的实现类之一,它提供了继承父 BeanDefinition 的能力,使得子 BeanDefinition 也能拥有父 BeanDefinition 的能力

用法

public static class Person extends User {
    private String nickName;

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    @Override
    public String toString() {
        return "Person{" +
                "nickName='" + nickName + '\'' +
                ", username='" + username + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

public static class User {
    protected String username;
    protected String address;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

@Test
void rbdTest() {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
    MutablePropertyValues mpv = new MutablePropertyValues();
    mpv.add("username", "yosoro");
    mpv.add("address", "cn");
    RootBeanDefinition rbd = new RootBeanDefinition(User.class, null, mpv);
    ctx.registerBeanDefinition("user", rbd);
    ChildBeanDefinition cbd = new ChildBeanDefinition("user");
    cbd.setBeanClass(Person.class);
    cbd.getPropertyValues().add("nickName", "wata");
    ctx.registerBeanDefinition("person", cbd);
    ctx.refresh();
    System.out.println(ctx.getBean("person", Person.class));
}

输出结果

Person{nickName='wata', username='yosoro', address='cn'}

GenericBeanDefinition

AbstractBeanDefinition 的实现类之一,同时涵盖了 RootBeanDefinition 和 ChildBeanDefinition 的能力

用法

User 跟 Person 类与 ChildBeanDefinition 一样,不一样的是 rbtTest() 的代码

@Test
void rbdTest() {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
    MutablePropertyValues mpv = new MutablePropertyValues();
    mpv.add("username", "yosoro");
    mpv.add("address", "cn");
    RootBeanDefinition rbd = new RootBeanDefinition(User.class, null, mpv);
    ctx.registerBeanDefinition("user", rbd);
    GenericBeanDefinition cbd = new GenericBeanDefinition(rbd);
    cbd.setBeanClass(Person.class);
    cbd.getPropertyValues().add("nickName", "wata");
    ctx.registerBeanDefinition("person", cbd);
    ctx.refresh();
    System.out.println(ctx.getBean("person", Person.class));
}

输出结果

Person{nickName='wata', username='yosoro', address='cn'}

AnnotatedGenericBeanDefinition

表示该 Bean 是包含 @Component 的注解,所有通过 @Component 相关的注解创建的 Bean 的 BeanDefinition,都是 AnnotatedGenericBeanDefinition 类型。

用法

// @Configuration 注解包含了 @Component 注解
@Configuration("testConfig")
public static class TestConfig {
    @Bean
    User testUser() {
        return new User();
    }
}
@Test
void configBeanTest() {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(TestConfig.class);
    // AnnotatedGenericBeanDefinition 类型
    BeanDefinition testConfigBeanDefinition = ctx.getBeanDefinition("testConfig");
    System.out.println(testConfigBeanDefinition.getClass());
    // ConfigurationClassBeanDefinitionReader$ConfigurationClassBeanDefinition 类型
    BeanDefinition testUserBeanDefinition = ctx.getBeanDefinition("testUser");
    System.out.println(testUserBeanDefinition.getClass());
}

输出结果

class org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition
class org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader$ConfigurationClassBeanDefinition

BeanFactoryPostProcessor

BeanFactoryPostProcessor 是在 beanFactory 创建 Bean 之前调用的,我们可以通过 BeanFactoryPostProcessor ,来修改 BeanDefinition 的属性值,以达到修改 Bean 的属性;

BeanFactoryPostProcessor 源码

public interface BeanFactoryPostProcessor {
    /*
    * Spring 在所有 BeanDefinition 加载完毕后,Bean 创建前调用
    * 可以通过该方法来修改 Bena 的属性值
    */
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

使用例子

// 自定义的 BeanFactoryPostProcessor
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        String beanName = "testBean";
        if(beanFactory.containsBeanDefinition(beanName)){
            BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
            bd.getPropertyValues().add("field","after change");
        }
    }
}
// 用到的 BeanClass
public class TestBean implements InitializingBean {
    protected Object field;

    public TestBean() {
        System.out.println("create TestBean");
    }

    public Object getField() {
        return field;
    }

    public void setField(Object field) {
        System.out.println("set field property");
        this.field = field;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("invoke afterPropertiesSet method");
    }

    @Override
    public String toString() {
        return "TestBean{" +
                "field=" + field +
                '}';
    }
}
// 测试代码
@SpringBootTest
public class CustomBeanFactoryPostProcessorTest {
    @Autowired
    private ApplicationContext ctx;

    @Test
    public void test(){
        TestBean testBean = ctx.getBean(TestBean.class,"testBean");
        System.out.println(testBean);
    }

    @Configuration
    static class Config{
        @Bean("testBean")
        public TestBean testBean(){
            TestBean testBean = new TestBean();
            testBean.setField("field value");
            return testBean;
        }

        @Bean
        public CustomBeanFactoryPostProcessor customBeanFactoryPostProcessor(){
            return new CustomBeanFactoryPostProcessor();
        }
    }
}

输出结果

TestBean{field=after change}

BeanDefinitionRegistryPostProcessor

BeanFactoryPostProcessor 的子类,可以用于手动添加 BeanDefinition ,以达到添加 Bean 的效果。

BeanDefinitionRegistryPostProcessor 源码

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

    /**
    * Spring 在调用该方法前,所有 BeanDefinition 已经加载完毕,Bean 创建前调用
    * 可以通过该方法来添加 Bean
    * 此外,Spring 先执行该方法,然后再执行 BeanFactoryPostProcessor 的 postProcessBeanFactory 方法
    */
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

使用例子

// 自定义的 BeanDefinitionRegistryPostProcessor
public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("invoke postProcessBeanFactory method");
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        RootBeanDefinition rbd = new RootBeanDefinition();
        rbd.setBeanClass(TestBean.class);
        rbd.getPropertyValues().add("field","test");
        registry.registerBeanDefinition("testBean",rbd);
        System.out.println("add TestBean finish");
    }
}
// 这里用到的 TestBean 类跟 BeanFactoryPostProcessor 的例子一样,故不贴
// 测试代码
@SpringBootTest
public class CustomBeanDefinitionRegistryPostProcessorTest {
    @Autowired
    private ApplicationContext ctx;

    @Test
    void test(){
        final TestBean bean = ctx.getBean(TestBean.class);
        System.out.println(bean);
    }

    @Configuration
    static class TestConfig{
        @Bean
        public CustomBeanDefinitionRegistryPostProcessor customBeanFactoryPostProcessor(){
            return new CustomBeanDefinitionRegistryPostProcessor();
        }
    }
}

输出结果:

add TestBean finish
invoke postProcessBeanFactory method
create TestBean
set field property
invoke afterPropertiesSet method
TestBean{field=test}

参考博客

  1. Spring 源码第四弹!深入理解 BeanDefinition
  2. Spring后置处理器之-BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor

你可能感兴趣的:(springjava)