1. 程式人生 > 其它 >Spring(3)-手動註冊BeanDefinition

Spring(3)-手動註冊BeanDefinition

大體思路:

1、選擇BeanDefinition的實現類,並例項化BeanDefinition

2、註冊BeanDefinition

3、獲取Bean,看看是不是正常工作的。

非抽象的實現類主要有三個

1、GenericBeanDefinition,這個也是官方推薦使用的,註釋裡提到可以動態設定parentbeandefinition等。

2、RootBeanDefinition,這個跟@Configuration註解有關。
3、ChildBeanDefinition,這個也可以實現設定parentbeandefinition,不過它是預先定義parent/child關係,官方也不推薦使用了,看註釋可以知道,從spring2.5開始

GenericBeanDefinition已經替代ChildBeanDefinition了。

基於以上思路,我們選擇GenericBeanDefinition

public class GenericBeanDefinition extends AbstractBeanDefinition {

    @Nullable
    private String parentName;


    /**
     * Create a new GenericBeanDefinition, to be configured through its bean
     * properties and configuration methods.
     * 
@see #setBeanClass * @see #setScope * @see #setConstructorArgumentValues * @see #setPropertyValues */ public GenericBeanDefinition() { super(); } /** * Create a new GenericBeanDefinition as deep copy of the given * bean definition. * @param original the original bean definition to copy from
*/ public GenericBeanDefinition(BeanDefinition original) { super(original); } @Override public void setParentName(@Nullable String parentName) { this.parentName = parentName; } @Override @Nullable public String getParentName() { return this.parentName; } @Override public AbstractBeanDefinition cloneBeanDefinition() { return new GenericBeanDefinition(this); } @Override public boolean equals(@Nullable Object other) { if (this == other) { return true; } if (!(other instanceof GenericBeanDefinition)) { return false; } GenericBeanDefinition that = (GenericBeanDefinition) other; return (ObjectUtils.nullSafeEquals(this.parentName, that.parentName) && super.equals(other)); } @Override public String toString() { if (this.parentName != null) { return "Generic bean with parent '" + this.parentName + "': " + super.toString(); } return "Generic bean: " + super.toString(); } }

框架裡面一般是怎麼使用GenericBeanDefinition的呢?

一般是在BeanDefinitionBuilder裡面,或者是BeanDefinitionReaderUtils,我記得是這個,由於這個筆記本不好用,簡單搜下

然後就是註冊BeanDefinition了

找一個beanFactory,

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
        implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

不只實現了ConfigurableListableBeanFactory,還實現了BeanDefinitionRegistry

public interface BeanDefinitionRegistry extends AliasRegistry {

    /**
     * Register a new bean definition with this registry.
     * Must support RootBeanDefinition and ChildBeanDefinition.
     * @param beanName the name of the bean instance to register
     * @param beanDefinition definition of the bean instance to register
     * @throws BeanDefinitionStoreException if the BeanDefinition is invalid
     * @throws BeanDefinitionOverrideException if there is already a BeanDefinition
     * for the specified bean name and we are not allowed to override it
     * @see GenericBeanDefinition
     * @see RootBeanDefinition
     * @see ChildBeanDefinition
     */
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException;

    ..........

}

所以,我們只要呼叫這個beanFactory的註冊方法即可。

生成beanName

BeanNameGenerator介面,有兩個實現類

public interface BeanNameGenerator {

    /**
     * Generate a bean name for the given bean definition.
     * @param definition the bean definition to generate a name for
     * @param registry the bean definition registry that the given definition
     * is supposed to be registered with
     * @return the generated bean name
     */
    String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry);

}

AnnatationBeanNameGenerator就是我們平時使用的註解方式@Autowired,的一個這樣的格式,而預設的beanName則是,類名稱+#+0(com.spring.learn.service.impl.TestServiceImpl#0)這樣的。

bean之間的依賴

通過constructor,或者property方式注入

之前不是說過BeanDefinition接口裡面有兩個引數,一個是關於建構函式,一個是關於屬性set方法注入的。

構造器注入程式碼

 GenericBeanDefinition controllerBeanDefinition = (GenericBeanDefinition) BeanDefinitionBuilder.
                genericBeanDefinition(TestControllerWithConstructor.class)
                .addConstructorArgValue("controller name is TestController")
                .addConstructorArgReference(testServiceName)
                .getBeanDefinition();

屬性值注入程式碼

        GenericBeanDefinition propertyControllerBeanDefinition = (GenericBeanDefinition) BeanDefinitionBuilder
                .genericBeanDefinition(TestControllerWithProperty.class)
                .addPropertyValue("name","name is property controller")
                .addPropertyReference("testService",testServiceName).getBeanDefinition();

完成注入程式碼:

 public static void main(String[] args) {
//        SpringApplication.run(SpringLearnApplication.class, args);
        //建立一個工廠來
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        //建立beanDefinition
        GenericBeanDefinition beanDefinition = (GenericBeanDefinition) BeanDefinitionBuilder.genericBeanDefinition(TestServiceImpl.class)
                .getBeanDefinition();
        //建立beanDefinition Name
        String testServiceName = AnnotationBeanNameGenerator.INSTANCE.generateBeanName(beanDefinition,beanFactory);
        //注入到spring 工廠裡
        beanFactory.registerBeanDefinition(testServiceName,beanDefinition);

        //建立controller,這個builder模式裡邊,要呼叫constructor的方法
        GenericBeanDefinition controllerBeanDefinition = (GenericBeanDefinition) BeanDefinitionBuilder.
                genericBeanDefinition(TestControllerWithConstructor.class)
                .addConstructorArgValue("controller name is TestController")
                .addConstructorArgReference(testServiceName)
                .getBeanDefinition();
        String controllerBeanName = AnnotationBeanNameGenerator.INSTANCE.generateBeanName(controllerBeanDefinition,beanFactory);
        beanFactory.registerBeanDefinition(controllerBeanName,controllerBeanDefinition);

        //---------------------------------------------
        //注入之後,再取出來,將controller裡面service和 spring裡面的service作對比是不是一樣的。
        TestControllerWithConstructor testController = (TestControllerWithConstructor) beanFactory.getBean(controllerBeanName);
        TestService testService = (TestService) beanFactory.getBean(testServiceName);
        Assert.isTrue(testController.getTestService()==testService,"他們不相等,有問題");


        //__________________________________________________
        //這個是通過屬性值property注入到DefaultListableBeanFactory
        GenericBeanDefinition propertyControllerBeanDefinition = (GenericBeanDefinition) BeanDefinitionBuilder
                .genericBeanDefinition(TestControllerWithProperty.class)
                .addPropertyValue("name","name is property controller")
                .addPropertyReference("testService",testServiceName).getBeanDefinition();
        String propertyControllerName = AnnotationBeanNameGenerator.INSTANCE.generateBeanName(propertyControllerBeanDefinition,beanFactory);
        beanFactory.registerBeanDefinition(propertyControllerName,propertyControllerBeanDefinition);
        //注入進去之後,再取出propertyController
        TestControllerWithProperty propertyController = (TestControllerWithProperty) beanFactory.getBean(propertyControllerName);
        System.out.println(propertyController.getName());
        Assert.isTrue(propertyController.getTestService()==testService,"他們不相等,有問題");

    }

https://www.cnblogs.com/grey-wolf/p/12070377.html

今天就到這了,我去看別的了,