• Spring BeanDefinition详解


    BeanDefinition是定义Bean的配置元信息的接口,包含:

    parentName父bean
    classNamebean类名
    scope作用域
    isLazyInit是否懒加载
    dependsOn依赖的bean
    isAutowireCandidate是否可以注入到其他bean中,类型注入有效,名称注入无效
    isPrimary是否主bean,同一个接口的多个实现,如果不指定名字,Spring会优先选择isPrimary为true的bean
    factoryBeanName工场bean的名称
    factoryMethodName工厂类的工厂方法名称
    ConstructorArgumentValues构造器参数
    PropertyValuesbean中的属性值
    isSingleton是否单例
    isPrototype是否多例
    isAbstract如果这个bean被设置成"abstract",那么它将不能实例化
    rolebean的角色APPLICATION – 指出该bean是应用程序的主要部分,通常对应用户定义的bean。SUPPORT – 应用支持性质的bean,在某些地方比较重要,但从整个应用的返回来看,还没那么重要。INFRASTRUCTURE – 基础设施bean,仅仅用于框架内部工作,跟终端用户无关。
    Descriptionbean的描述
    ResourceDescription资源描述文本,告知当前bean定义的来源,一般用于错误时显示上下文
    OriginatingBeanDefinition返回来源bean定义(如果有的话)。通过该属性,可以获取被修饰的bean定义。需要注意的是该属性仅仅返回直接来源bean定义而不是返回最深处的来源bean定义。一个bean定义的originatingBeanDefinition属性隐含了一个来源bean定义链,通过迭代访问该链,可以最终找到最终来自用户的bean定义。

    img

    Spring Bean的总体创建过程如下,Spring会加载指定的java类将其变成BeanDefinition对象,然后根据BeanDefinition来创建Bean

    img

    继承体系

    img

    从类图中可以看出,BeanDefinition继承了AttributeAccessor和BeanMetadataElement两个接口;

    AttributeAccessor

    //将name定义的属性设置为提供的value值。如果value的值为null,则该属性为{@link #removeAttribute removed}。
    //通常,用户应该注意通过使用完全限定的名称(可能使用类或包名称作为前缀)来防止与其他元数据属性重叠。
    void setAttribute(String name, Object value);
    //获取标识为name的属性的值。
    Object getAttribute(String name);
    //删除标识为name的属性,并返回属性值
    Object removeAttribute(String name);
    //如果名为name的属性是否存在,存在返回true,否则返回false。
    boolean hasAttribute(String name);
    //返回所有属性的名称。
    String[] attributeNames();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    BeanMetadataElement

    //返回此元数据元素的配置源对象(可能为null)。
    Object getSource();
    
    • 1
    • 2

    AnnotatedBeanDefinition

    AnnotatedBeanDefinitionBeanDefinition的子接口之一,扩展了两个方法,一般情况下通过注解方式得到的bean,其BeanDefinition类型都是该接口的实现类

    public interface AnnotatedBeanDefinition extends BeanDefinition {
        // 获取当前bean的注解元数据
    	AnnotationMetadata getMetadata();
        // 获取当前bean的工厂方法上的元数据
    	@Nullable
    	MethodMetadata getFactoryMethodMetadata();
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    AbstractBeanDefinition

    AbstractBeanDefinition是最终全能BeanDefinition实现类的基类,也是这些类的公同属性和公共逻辑的实现

    部分源码:

    public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
    		implements BeanDefinition, Cloneable {
    //	默认的SCOPE,默认是单例
    	public static final String SCOPE_DEFAULT = "";
    
    //	不进行自动装配
    	public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;
    
    //	根据Bean的名字进行自动装配,即autowired属性的值为byname
    	public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
    
    //	根据Bean的类型进行自动装配,调用setter函数装配属性,即autowired属性的值为byType
    	public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
    
    //	自动装配构造函数的形参,完成对应属性的自动装配,即autowired属性的值为byConstructor
    	public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
    
    //通过Bean的class推断适当的自动装配策略(autowired=autodetect),如果Bean定义有有参构造函数,则通过自动装配构造函数形参,完成对应属性的自动装配(AUTOWIRE_CONSTRUCTOR),否则,使用setter函数(AUTOWIRE_BY_TYPE)
    	@Deprecated
    	public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
    
    	//	不进行依赖检查
    	public static final int DEPENDENCY_CHECK_NONE = 0;
    
    	//	如果依赖类型为对象引用,则需要检查
    	public static final int DEPENDENCY_CHECK_OBJECTS = 1;
    
    	//	对简单属性的依赖进行检查
    	public static final int DEPENDENCY_CHECK_SIMPLE = 2;
    	//	对所有属性的依赖进行检查
    	public static final int DEPENDENCY_CHECK_ALL = 3;
    
    	//若Bean未指定销毁方法,容器应该尝试推断Bean的销毁方法的名字
    	public static final String INFER_METHOD = "(inferred)";
    
    	//	Bean的class对象或是类的全限定名
    	@Nullable
    	private volatile Object beanClass;
    
    	//bean的作用范围,对应bean属性scope是单例
    	@Nullable
    	private String scope = SCOPE_DEFAULT;
    
    	//是否是抽象,对应bean属性abstract 	默认不为抽象类
    	private boolean abstractFlag = false;
    	
    	//是否延迟加载,对应bean属性lazy-init
    	@Nullable
    	private Boolean lazyInit;
    	//	默认不进行自动装配
    	private int autowireMode = AUTOWIRE_NO;
    	//	默认不进行依赖检查
    	private int dependencyCheck = DEPENDENCY_CHECK_NONE;
    
    	//用来表示一个bean的实例化依靠另一个bean先实例化
    	//这里只会存放标签的depends-on属性或是@DependsOn注解的值
    	@Nullable
    	private String[] dependsOn;
    
    	//autowire-candidate属性设置为false,这样容器在查找自动装配对象时,
      	//将不考虑该bean,即它不会被考虑作为其他bean自动装配的候选者,
        //但是该bean本身还是可以使用自动装配来注入其他bean的
    	private boolean autowireCandidate = true;
    	
    	//自动装配时出现多个bean候选者时,将作为首选者,对应bean属性primary
    	private boolean primary = false;
    
    	//用于记录Qualifier,对应子元素qualifier
    	private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>();
    
    	@Nullable
    	private Supplier<?> instanceSupplier;
    
    	//允许访问非公开的构造器和方法,程序设置
    	private boolean nonPublicAccessAllowed = true;
    
    	//是否以一种宽松的模式解析构造函数,默认为true
    	private boolean lenientConstructorResolution = true;
    	
    	//对应bean属性factory-bean 工厂类名
    	@Nullable
    	private String factoryBeanName;
    	
    	//对应bean属性factory-method 工厂方法名
    	@Nullable
    	private String factoryMethodName;
    	
    	//记录构造函数注入属性,对应bean属性constructor-arg
    	@Nullable
    	private ConstructorArgumentValues constructorArgumentValues;
    	
    	//普通属性集合
    	@Nullable
    	private MutablePropertyValues propertyValues;
    	
    	//方法重写的持有者,记录lookup-method、replaced-method元素
    	private MethodOverrides methodOverrides = new MethodOverrides();
    	
    	//初始化方法,对应bean属性init-method
    	@Nullable
    	private String initMethodName;
    	
    	//销毁方法,对应bean属性destroy-method
    	@Nullable
    	private String destroyMethodName;
    
    	//是否执行init-method,程序设置
    	private boolean enforceInitMethod = true;
    
    	//是否执行destroy-method,程序设置
    	private boolean enforceDestroyMethod = true;
    	//是否是用户定义的而不是应用程序本身定义的,创建AOP时候为true,程序设置
    	private boolean synthetic = false;
    	//定义这个bean的应用,APPLICATION:用户,INFRASTRUCTURE:完全内部使用,与用户无关
    	private int role = BeanDefinition.ROLE_APPLICATION;
    	
    	//bean的描述信息
    	@Nullable
    	private String description;
    	//bean的资源
    	@Nullable
    	private Resource resource;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122

    继承自AbstractBeanDefinition的全功能BeanDefinition实现类有 :

    RootBeanDefinition、GenericBeanDefinition、ChildBeanDefinition

    RootBeanDefinition– 不能设置parent bean定义

    由此可见,RootBeanDefinition不能用于用于父子bean定义关系中的"子bean定义"

    ChildBeanDefinition – 必须设置parent bean定义,而且必须是通过构造函数指定

    ChildBeanDefinition很适合父子bean定义关系明确的情况下基于双亲bean定义和自身少量设置一些个性化属性从而进行子bean定义。

    实际上,真正在创建子bean定义规定的bean对象时,Spring框架内部是将双亲bean定义和孩子bean定义合并形成一个最终使用的RootBeanDefinition,这里孩子bean定义中设置的属性会被优先使用,没有指定的都会继承使用双亲bean定义中的设置。

    GenericBeanDefinition – 可以动态设置parent bean定义,也可以不设置parent bean定义

    由此可见,GenericBeanDefinition既可以替代 RootBeanDefinition,也可以替代ChildBeanDefinition,所以GenericBeanDefinition更一般化(generic)

  • 相关阅读:
    Go编程:使用 Colly 库下载Reddit网站的图像
    分享一下商城小程序怎么设置分销功能
    excel一列同乘同一个数
    redis下载与安装(Linux环境下)
    LeetCode 59. 螺旋矩阵 II【数组,模拟】中等
    vue3+ts+uniapp小程序封装获取授权hook函数
    算法 - 递归实现汉诺塔(The Tower of Hanoi)
    【VUE复习·6】监视属性watch:用途、两种写法、简写、应用时注意事项(重点)、深度监视(重点)
    关于队里面最菜的在博客打卡第六十二天这件事
    【计算机视觉40例】案例15:KNN数字识别
  • 原文地址:https://blog.csdn.net/qq_43460095/article/details/126017238