zoukankan      html  css  js  c++  java
  • Spring(3)手动注册BeanDefinition

    大体思路:

    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

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

  • 相关阅读:
    牛客(47)求1+2+3+...+n
    牛客(48)不用加减乘除做加法
    【推荐】可编程的热键 AutoHotkey
    【Web】js 简单动画,犯了低级错误
    【分享】JDK8u241 win x64度盘下载
    【Web】开始学Web开发!
    【数组】深析 “数组名称”
    【基础向】浅析 "多(二)维数组" 的三种引用方法
    【一个小错误】通过数组指针引用数组成员
    【网络通信教程】windows 下的 socket API 编程(TCP协议)
  • 原文地址:https://www.cnblogs.com/fuckingPangzi/p/15738051.html
Copyright © 2011-2022 走看看