美文网首页
自定义 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