spring-相关知识点-AbstractBeanDefinition

本文深入探讨Spring框架中BeanDefinition的使用与实现细节,包括属性分析、作用域设置、构造参数处理、初始化与销毁方法等关键功能。通过具体代码演示,帮助读者理解如何在Spring中管理和操作Bean。

前言

  • 在了解 spring 源码 的是我们知道 我们的Bean 都会被包装成 BeanDefinition进行操作
  • 所以需要对其有一个基本的了解
  • 这是一个抽象类
  • 其子类有
    • RootBeanDefinition
    • GenericBeanDefinition
  • 该类封装了大部分了操作 BeanDefinition 的操作 你所知道的一些属性 甚至一些操作都在这个类…

属性分析

参考了

applyDefaults

  • 传递一个 BeanDefinitionDefaults 对象进行一些默认值的填充…没啥可说的… 就是为了方便填充的一个方法,比如当你需要批量这么做的时候就可以定义一个 这样的对象…进行属性填充~~~
  • 比如去扫描的时候…因为这个方法就是在 扫描的时候去用的…

BeanClass相关方法

  • setBeanClassName() 设置Bean的ClassName,这个方法比较有意思,有意思在那下面去看
	// 设置Bean的ClassName 赋值给 BeanClass
	public void setBeanClassName(@Nullable String beanClassName) {
		this.beanClass = beanClassName;
	}
  • getBeanClassName() 这个方法比较有意思… 从setBeanClassName看的话我们设置的是String 为啥要做一个判断呢… 嘻嘻,那是因为还有一个方法会进行覆盖…
	public String getBeanClassName() {
	    // 获取 beanClass Name
		Object beanClassObject = this.beanClass;
		//  如果当前类本身就是 Class 类型的话 就获取Name
        //  如果不是则直接返回 beanClass ,因为此时 beanClass 可能还是 字符串
		if (beanClassObject instanceof Class) {
			return ((Class<?>) beanClassObject).getName();
		}
		else {
			// 如果不是Class 类型就代表本身就是String那就强制返回
			return (String) beanClassObject;
		}
	}
  • setBeanClass () 这个方法就是设置一个Class 赋值给BeanClass 是跟 setBeanClassName 逻辑是一样一样的,那为啥要这么做呢 ?我们来做一个实验
	public void setBeanClass(@Nullable Class<?> beanClass) {
		this.beanClass = beanClass;
	}
  • getClass()
	public Class<?> getBeanClass() throws IllegalStateException {
		//  这里获取Bean的Class 这里我们知道BeanClass 可能是 Class 类型 也可能是 String 类型
		Object beanClassObject = this.beanClass;
		if (beanClassObject == null) {
			// 抛出异常
		}
		//  这里如果 不是CLass 就会抛出异常,
		//  所以一般在调用这个方法之前会调用 hasBeanClass() 判断一下到底beanClass 是不是  
		//  class 类型,除非你能确定这个就是Class 类型,比如我们手动设置API~~~
		if (!(beanClassObject instanceof Class)) {
			// 抛出异常
		}
		return (Class<?>) beanClassObject;
	}
  • hasBeanClass() 判断 这个BeanClass 是否存在,上面已经详细讲过这个是为啥了…下面会用例子说明这个问题

  • resolveBeanClass() 简单说用于将ClassName转成Class…

	public Class<?> resolveBeanClass(@Nullable ClassLoader classLoader) throws ClassNotFoundException {
		// 获取ClassName
		String className = getBeanClassName();
		if (className == null) {
			return null;
		}
		// 根据Name 获取 Class 类型
		Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
		//  将 Class 类型 赋值给 beanClass ,此时的beanClass(字符串) 转换成了 Class 类型
		this.beanClass = resolvedClass;
		return resolvedClass;
	}
  • 产生的疑问,我们并没有设置Class呀,这个User 对象是怎么被创建的?
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        BeanDefinitionBuilder userBeanBuilder = BeanDefinitionBuilder.genericBeanDefinition();
        AbstractBeanDefinition beanDefinition = userBeanBuilder.getBeanDefinition();
        // 可以看到这里我们设置的 仅仅是这个User.class的Name 并不是设置的Class
        beanDefinition.setBeanClassName(User.class.getName());
        beanFactory.registerBeanDefinition("user",beanDefinition);
        User bean = beanFactory.getBean(User.class);
        System.out.println(bean);
        AbstractBeanDefinition user = (AbstractBeanDefinition) beanFactory.getBeanDefinition("user");
        System.out.println(beanDefinition==user);

    }
  • 稍微略一下 创建的源码你就会知道了~~
  • AbstractBeanFactory.resolveBeanClass()// 这个方法是去获取Class 去了…可以直接DBUG到这个地方看看
protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)
        throws CannotLoadBeanClassException {
		// 删除了一些没啥影响的代码
		
        // 是否存在 BeanClass 定义, 这里就是去判断去了,可是我传递的是String ,所以是不存在的
        if (mbd.hasBeanClass()) {
            // 返回BeanClass,如果我们设置的类型是Class 就会直接返回
            return mbd.getBeanClass();
        }
       // 这里就代表没设置.. 那就会去通过 我们设置的Name 去获取这个Class,这里可以自己去跟源码,由于本文就不是讲解这些源码的所以就不过多的渗透进去了
       return doResolveBeanClass(mbd, typesToMatch);
}

Singleton相关代码演示

  • 用于设置作用域…
    • getSingleton --如果没有设置去get的时候默认是 "" 空串,代表了单例
    • setSingleton
    • isSingleton --判断是否是单例,如果设置了singleton 或者是空就代表是单例
    • isPrototype --判断是否是原型…
   private static final DefaultListableBeanFactory beanFactory;
   private static final AbstractBeanDefinition beanDefinition;
    static{
        beanFactory = new DefaultListableBeanFactory();
        beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        beanDefinition.setBeanClassName(User.class.getName());
        beanFactory.registerBeanDefinition("user", beanDefinition);
    }

    public static void main(String[] args) {
    // 判断单例还是 原型,还有一些 request session 等需要WEB的支持了..
//        beanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);
        beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);

        if(beanDefinition.isPrototype ()){
            for (int i = 0; i <5; i++) {
                User bean = beanFactory.getBean(User.class);
                System.out.println(bean);
            }
        }else{
            for (int i = 0; i <5; i++) {
                User bean = beanFactory.getBean(User.class);
                System.out.println(bean);
            }
        }
    }

Bean构造参数演示

  • 构造器
    • getConstructorArgumentValues – 获取构造器参数
    • setConstructorArgumentValues – 设置构造器参数
    • hasConstructorArgumentValues --判断存在构造器参数
  • 如果 存在构造器函数参数,则就会去创建有参的构造函数,不会去创建无参的构造
    private static final DefaultListableBeanFactory beanFactory;
    private static final AbstractBeanDefinition beanDefinition;

    static {
        beanFactory = new DefaultListableBeanFactory();
        beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        beanDefinition.setBeanClassName(User.class.getName());
        beanFactory.registerBeanDefinition("user", beanDefinition);
    }
    private static void constructorArgumentValues() {
        ConstructorArgumentValues value = new ConstructorArgumentValues();
        value.addIndexedArgumentValue(0, "北京");
        value.addIndexedArgumentValue(1, "张三");
        value.addIndexedArgumentValue(2, 99);
        beanDefinition.setConstructorArgumentValues(value);
        System.out.println(getBean());

    }
  • 源码
AbstractAutowireCapableBeanFactory.createBeanInstance()
  • 这里会有一个判断,判断是否存在 构造器参数,如果存在则就会执行有参构造器,无参构造器还没执行到~~

在这里插入图片描述

Bean参数设置

  • 属性
    • setPropertyValues 属性
    • getPropertyValues
    • hasPropertyValues

初始化、销毁方法

  • setInitMethodName – 初始化方法
  • setEnforceInitMethod – 设置是否启动 初始化方法 (这里不用过多关注…)
  • isEnforceInitMethod – 判断是否启动了初始化方法 (这里不用过多关注…)
  • setDestroyMethodName 销毁方法

其他功能方法

* setAbstract --设置为抽象的..如果设置为true也就是说不会进行实例化
* isAbstract   --判断是否是抽象的	
* setLazyInit 设置懒加载
* isLazyInit 判断是否是懒加载  
* getLazyInit 获取..懒加载
* setAutowireMode 设置自动装配 
* getAutowireMode 获取自动装配 --默认是 AUTOWIRE_NO 不进行自动装配
* setPrimary 设置是否是主要的
* isPrimary  判断是否为主要''

factory相关

  • setFactoryBeanName --设置
  • getFactoryBeanName --获取
  • setFactoryMethodName --设置方法
  • getFactoryMethodName --获取方法

这一个个的API 我就想一一演示的

可以自行去演示玩玩看

    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        beanDefinition.setBeanClassName(User.class.getName());
		// 设置直接去设置 BeanDefinition 就好了,比如我设置一个原型,就可以看到每次创建的对象都不一样...
		 beanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);
		 
        beanFactory.registerBeanDefinition("user", beanDefinition);
}

但是可以明确的是 spring 就是这么玩的… 不管是XML 还是注解还是 外部配置等…

相关文章

GenericBeanDefinition-分析
AbstractBeanDefinition分析
BeanMetadataAttributeAccessor 分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值