ICode9

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

Spring(3)-手动注册BeanDefinition

2021-12-27 22:03:15  阅读:268  来源: 互联网

标签:definition GenericBeanDefinition name beanFactory Spring 手动 bean public BeanDefi


大体思路:

1、选择BeanDefinition的实现类,并实例化BeanDefinition

2、注册BeanDefinition

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

非抽象的实现类主要有三个

1、GenericBeanDefinition,这个也是官方推荐使用的,注释里提到可以动态设置parent bean definition等。

2、RootBeanDefinition,这个跟@Configuration注解有关。
3、ChildBeanDefinition,这个也可以实现设置parent bean definition,不过它是预先定义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

今天就到这了,我去看别的了,

标签:definition,GenericBeanDefinition,name,beanFactory,Spring,手动,bean,public,BeanDefi
来源: https://www.cnblogs.com/fuckingPangzi/p/15738051.html

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

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

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

ICode9版权所有