美文网首页
自定义 BeanDefinition

自定义 BeanDefinition

作者: 蓝笔头 | 来源:发表于2021-07-08 17:36 被阅读0次

    BeanDefinition 描述了一个 bean 实例,它具有属性值、构造函数参数值以及由具体实现提供的更多信息。

    BeanDefinition 中需要用到的方法

    // BeanDefinition 描述了一个 bean 实例,它具有属性值、构造函数参数值以及由具体实现提供的更多信息。
    public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    ...
        //配置 Bean 的 Class 全路径
        void setBeanClassName(@Nullable String beanClassName);
        
        // 配置 Bean 是否是自动装配的候选者
        void setAutowireCandidate(boolean autowireCandidate);
        
        // 如果找到了多个可注入bean
        // 则选择被Primary标记为首选的 Bean
        void setPrimary(boolean primary);
        
        // 配置 FactoryBean 的名字
        void setFactoryBeanName(@Nullable String factoryBeanName);
        
        // 配置 FactoryMethod 的名字,和 FactoryBean 配合使用
        // 可以是某个实例的方法,也可以是静态方法
        void setFactoryMethodName(@Nullable String factoryMethodName);
        
    }
    
    // 具体的、成熟的 BeanDefinition 类的基类
    // 分解出 GenericBeanDefinition、RootBeanDefinition 和 ChildBeanDefinition 的通用属性。
    // 自动装配常量与 AutowireCapableBeanFactory 接口中定义的常量相匹配。
    public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
            implements BeanDefinition, Cloneable {
    ... 
        // 指定此 bean 的构造函数参数值
        public void setConstructorArgumentValues(ConstructorArgumentValues constructorArgumentValues);
        
        
        // 指定此 bean 的属性值(如果有)
        public void setPropertyValues(MutablePropertyValues propertyValues);
    }
            
    

    (一)通过构造函数实例化 Bean

    1)测试类 User

    @Data
    public class User {
        private Long id;
        private String name;
    }
    

    2)自定义 RootBeanDefinition,注册到 Spring 容器中

    public class TestBeanDefinition {
        public static void main(String[] args) {
            DefaultListableBeanFactory context = new DefaultListableBeanFactory();
    
            // 1. 实例化一个 RootBeanDefinition
            RootBeanDefinition beanDefinition = new RootBeanDefinition();
            // 2. 设置 BeanClass
            beanDefinition.setBeanClass(User.class);
    
            // 3. 设置 构造方法对应的属性值
            ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
            constructorArgumentValues.addGenericArgumentValue(1L);
            constructorArgumentValues.addGenericArgumentValue("huhu");
            beanDefinition.setConstructorArgumentValues(constructorArgumentValues);
    
            // 4. 注册到 Spring 容器中
            context.registerBeanDefinition("user", beanDefinition);
    
            System.out.println(context.getBean("user"));
        }
    }
    

    3)控制台输出:

    15:45:03.441 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'user'
    User(id=1, name=huhu)
    

    4)源码位置

    package org.springframework.beans.factory.support;
    
    public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
            implements AutowireCapableBeanFactory {
    ...
        protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
            ... 
            // Candidate constructors for autowiring?
            // mbd.hasConstructorArgumentValues() 表示设置了 ConstructorArgumentValues
            Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
            if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
                    mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
                // 选择合适的构造函数,并进行实例化操作
                return autowireConstructor(beanName, mbd, ctors, args);
            }
            ...
        }
    }
    

    (二)实例化 Bean 后通过 Setter 方法进行属性赋值

    1)测试代码:

    public class TestBeanDefinition {
        public static void main(String[] args) {
            DefaultListableBeanFactory context = new DefaultListableBeanFactory();
    
            // 1. 实例化一个 RootBeanDefinition
            RootBeanDefinition beanDefinition = new RootBeanDefinition();
            // 2. 设置 BeanClass
            beanDefinition.setBeanClass(User.class);
    
            // 3. 设置 构造方法对应的属性值
            ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
            constructorArgumentValues.addGenericArgumentValue(1L);
            constructorArgumentValues.addGenericArgumentValue("huhu");
            beanDefinition.setConstructorArgumentValues(constructorArgumentValues);
    
            // 4. 注册到 Spring 容器中
            context.registerBeanDefinition("user", beanDefinition);
    
            System.out.println(context.getBean("user"));
        }
    }
    

    2)源码位置

    package org.springframework.beans.factory.support;
    
    public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
            implements AutowireCapableBeanFactory {
    ...
        protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                throws BeanCreationException {
            ...
            
            // Instantiate the bean.
            BeanWrapper instanceWrapper = null;
            if (instanceWrapper == null) {
                // 1. 实例化 bean 对象
                instanceWrapper = createBeanInstance(beanName, mbd, args);
            }
    
    
            // Initialize the bean instance.
            // 3. 初始化 Bean,通过 Setter 方法
            populateBean(beanName, mbd, instanceWrapper);
            
            ...
        }
        
        protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
            ... 
            // No special handling: simply use no-arg constructor.
            // 2. 通过无参数构造函数实例化对象
            return instantiateBean(beanName, mbd);
        }
        
        protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
            ...
            // 4. 获取 BeanDefinition 中配置的 PropertyValues
            PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
            if (pvs != null) {
                // 5. 调用 setter 方法进行设置
                applyPropertyValues(beanName, mbd, bw, pvs);
            }
            ...
        }
    }
    

    (三)通过工厂方法实例化对象

    (3.1)源码解读

    package org.springframework.beans.factory.support;
    
    public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
            implements AutowireCapableBeanFactory {
    ...
        protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
            // 如果工厂方法不为空,通过工厂方法实例化 bean 对象
            if (mbd.getFactoryMethodName() != null) {
                return instantiateUsingFactoryMethod(beanName, mbd, args);
            }
        }
        ...
    }
    
    package org.springframework.beans.factory.support;
    class ConstructorResolver {
        public BeanWrapper instantiateUsingFactoryMethod(
                String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
    
            BeanWrapperImpl bw = new BeanWrapperImpl();
            this.beanFactory.initBeanWrapper(bw);
    
            Object factoryBean;
            Class<?> factoryClass;
            boolean isStatic;
    
    
            // 1. 获取 factoryBeanName
            String factoryBeanName = mbd.getFactoryBeanName();
            if (factoryBeanName != null) {
                // 2. 获取 factoryBean
                factoryBean = this.beanFactory.getBean(factoryBeanName);
                factoryClass = factoryBean.getClass();
                isStatic = false;
            }
            else {
                // It's a static factory method on the bean class.
                // 3. 没有设置 factoryBeanName 表示为静态的工厂方法
                factoryBean = null;
                factoryClass = mbd.getBeanClass();
                isStatic = true;
            }
            
            if (factoryMethodToUse == null || argsToUse == null) {
                // Need to determine the factory method...
                // Try all methods with this name to see if they match the given arguments.
                factoryClass = ClassUtils.getUserClass(factoryClass);
    
                
                List<Method> candidates = null;
                // 4. 选择合适的候选工厂方法
                // static 修饰符是否符合条件 && methodName 是否符合条件
                if (candidates == null) {
                    candidates = new ArrayList<>();
                    Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
                    for (Method candidate : rawCandidates) {
                        if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
                            candidates.add(candidate);
                        }
                    }
                }
    
                
                // 5. 获取配置的 ConstructorArgumentValues 参数
                ConstructorArgumentValues resolvedValues = null;    
                if (mbd.hasConstructorArgumentValues()) {
                    ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
                    resolvedValues = new ConstructorArgumentValues();
                    resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
                }
            
    
                Deque<UnsatisfiedDependencyException> causes = null;
    
                // 6. 找到符合条件的工厂方法,并赋值给 factoryMethodToUse
                for (Method candidate : candidates) {
                    factoryMethodToUse = candidate;
                }
            }
    
            // 7. 通过工厂方法实例化 bean 对象
            bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
            return bw;
        }
    }
    

    (3.2)静态方法实例化 Bean 对象

    1)定义工厂类

    public class UserFactory {
        // 不带参数的工厂方法
        public static User getUser() {
            return User.builder()
                .id(100L)
                .name("who are you")
                .build();
        }
    
        // 带参数的工厂方法
        public static User getUser(long id, String name) {
            return User.builder()
                .id(id)
                .name(name)
                .build();
        }
    }
    

    2)无参的工厂方法实例化 Bean 对象

    public class TestBeanDefinition {
        public static void main(String[] args) {
            DefaultListableBeanFactory context = new DefaultListableBeanFactory();
    
            // 1. 实例化一个 RootBeanDefinition
            RootBeanDefinition beanDefinition = new RootBeanDefinition();
    
            // 2. 设置工厂方法和工厂类
            // 这里的 BeanClass 是工厂类
            beanDefinition.setFactoryMethodName("getUser");
            beanDefinition.setBeanClass(UserFactory.class);
    
            // 3. 注册到 Spring 容器中
            context.registerBeanDefinition("user", beanDefinition);
    
            System.out.println(context.getBean("user"));
        }
    }
    

    控制台输出:

    13:20:42.071 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'user'
    User(id=100, name=who are you)
    

    3)有参数的工厂方法实例化 Bean 对象

    public class TestBeanDefinition {
        public static void main(String[] args) {
            DefaultListableBeanFactory context = new DefaultListableBeanFactory();
    
            // 1. 实例化一个 RootBeanDefinition
            RootBeanDefinition beanDefinition = new RootBeanDefinition();
    
            // 2. 设置工厂方法和工厂类
            // 这里的 BeanClass 是工厂类
            beanDefinition.setFactoryMethodName("getUser");
            beanDefinition.setBeanClass(UserFactory.class);
    
            // 3. 设置 FactoryMethodName 的参数
            ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
            constructorArgumentValues.addGenericArgumentValue(1L);
            constructorArgumentValues.addGenericArgumentValue("huhu");
            beanDefinition.setConstructorArgumentValues(constructorArgumentValues);
    
            // 4. 注册到 Spring 容器中
            context.registerBeanDefinition("user", beanDefinition);
    
            System.out.println(context.getBean("user"));
        }
    }
    

    控制台输出:

    13:22:34.074 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'user'
    User(id=1, name=huhu)
    

    (3.3)成员方法实例化 Bean 对象

    1)定义工厂类,并通过 @Component 注入到 Spring 容器中。

    @Component
    public class UserFactory {
        // 不带参数的工厂方法
        public User getUser() {
            return User.builder()
                .id(2000L)
                .name("I am the King")
                .build();
        }
    
        // 带参数的工厂方法
        public User getUser(long id, String name) {
            return User.builder()
                .id(id)
                .name(name)
                .build();
        }
    }
    

    2)无参的工厂方法实例化 Bean 对象

    @Component
    @Slf4j
    public class RegistryCommandLineRunner implements CommandLineRunner{
        @Autowired
        private DefaultListableBeanFactory context;
    
        @Override
        public void run(String... args) throws Exception {
            // 1. 实例化一个 RootBeanDefinition
            RootBeanDefinition beanDefinition = new RootBeanDefinition();
    
            // 2. 设置 FactoryBeanName 和 FactoryMethodName
            // FactoryBeanName 是工厂类在 Spring 容器中的 beanName
            // FactoryMethodName 是工厂类用来生成当前 Bean 的方法
            beanDefinition.setFactoryBeanName("userFactory");
            beanDefinition.setFactoryMethodName("getUser");
    
            // 3. 注册到 Spring 容器中
            context.registerBeanDefinition("user", beanDefinition);
    
            System.out.println(context.getBean("user"));
        }
    }
    

    控制台输出:

    User(id=2000, name=I am the King)
    

    3)有参数的工厂方法实例化 Bean 对象

    @Component
    @Slf4j
    public class RegistryCommandLineRunner implements CommandLineRunner{
        @Autowired
        private DefaultListableBeanFactory context;
    
        @Override
        public void run(String... args) throws Exception {
            // 1. 实例化一个 RootBeanDefinition
            RootBeanDefinition beanDefinition = new RootBeanDefinition();
    
            // 2. 设置 FactoryBeanName 和 FactoryMethodName
            // FactoryBeanName 是工厂类在 Spring 容器中的 beanName
            // FactoryMethodName 是工厂类用来生成当前 Bean 的方法
            beanDefinition.setFactoryBeanName("userFactory");
            beanDefinition.setFactoryMethodName("getUser");
    
            // 3. 设置 FactoryMethodName 的参数
            ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
            constructorArgumentValues.addGenericArgumentValue(1L);
            constructorArgumentValues.addGenericArgumentValue("huhu");
            beanDefinition.setConstructorArgumentValues(constructorArgumentValues);
    
            // 4. 注册到 Spring 容器中
            context.registerBeanDefinition("user", beanDefinition);
    
            System.out.println(context.getBean("user"));
        }
    }
    

    控制台输出:

    User(id=1, name=huhu)
    

    参考

    相关文章

      网友评论

          本文标题:自定义 BeanDefinition

          本文链接:https://www.haomeiwen.com/subject/mxetpltx.html