首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

八股一下:Spring IoC容器中的BeanDefinition接口

文章目录:

一、BeanDefinition简介

二、BeanDefinition源码分析

1、常量

2、方法

3、继承接口

三、BeanDefinition简单应用

四、最后总结

一、BeanDefinition简介

在Spring框架中,BeanDefinition是用来描述Spring容器中Bean的元数据信息的接口,它包含了Bean的类信息、属性信息、行为特性、依赖关系和配置信息。

Bean的类信息:Bean的全限定类名,即这个Bean实例化后的具体类型。

Bean的属性信息:包括了Bean的作用域(单例or原型);是否为主要的(primary)、描述信息等等。

Bean的行为特性:Bean是否支持延迟加载,是否可以作为自动装配的候选者、以及Bean的初始化方法和销毁方法。

Bean的依赖关系:Bean所依赖的其他Bean,以及这个Bean是否有父Bean。

Bean的配置信息:Bean的构造器函数、属性值等。

BeanDefinition接口定义了Spring容器如何实例化、配置和管理Bean的规范,它是Spring IoC容器的核心概念之一。

在Spring容器启动时,会根据BeanDefinition中的信息来实例化和配置Bean,然后将这些Bean注册到容器中,以便后续的使用。

BeanDefinition可以通过XML配置、注解、Java配置等方式进行定义,Spring容器会解析这些定义,然后根据BeanDefinition来创建和管理Bean实例。

二、BeanDefinition源码分析

1、常量

1.1 bean的作用域

SCOPE_SINGLETON:表示Bean的作用域为singleton(单例模式)。在这种作用域下,Spring容器中的每个Bean定义只会创建一个实例,无论是通过构造函数创建还是通过工厂方法创建,容器会缓存这个实例并在需要时返回同一个实例。

SCOPE_PROTOTYPE:表示Bean的作用域为prototype(原型模式)。在这种作用域下,每次从容器中获取Bean时,容器都会创建一个新的实例并返回。

通过使用这些常量,可以清晰地表达Bean的作用域,有助于我们更好地理解和管理Bean的生命周期和实例化方式。

1.2 bean的角色

ROLE_APPLICATION:表示应用程序级别的Bean,它是应用程序开发者定义的Bean,用于实现应用程序的业务逻辑。这些Bean通常是应用程序的核心组件,包括Service、Repository、Controller等。

ROLE_SUPPORT:表示支持级别的Bean,它是为了支持应用程序级别的Bean而存在的,通常是一些工具类、辅助类或者基础设施类。这些Bean不直接参与业务逻辑的实现,而是为应用程序级别的Bean提供支持。

ROLE_INFRASTRUCTURE:表示基础设施级别的Bean,它是Spring框架内部使用的一些基础设施组件,比如AOP代理、事件发布器、BeanPostProcessor等。这些Bean通常是框架内部使用的,对应用程序开发者来说是透明的。

通过使用这些常量,Spring框架可以更清晰地表达Bean的角色和用途,有助于我们更好地理解和管理Bean的定义和使用。

2、方法

get/setParentName 获取/设置父类的名称

get/setBeanClassName  获取/设置Bean的类名

get/setScope 获取/设置Bean的作用域

get/setLazyInit 获取/设置是否延迟初始化

get/setDependsOn  获取/设置依赖的Beans

get/setAutowireCandidate  获取/设置是否可以自动装配

get/setPrimary  获取/设置是否首选的自动装配Bean

get/setFactoryMethodName 获取/设置工厂方法名称

has/getConstructorArgumentValues 判断/获取构造函数参数值

has/getPropertyValues 判断和获取属性值

get/setInitMethodName 获取/设置初始化方法名

get/setDestroyMethodName 获取/设置销毁方法名

get/setRole 获取/设置角色

get/setDescription 获取和设置描述信息

isSingleton/isPrototype/isAbstract 判断Bean是否单例/原型/抽象

getOriginatingBeanDefinition 获取原生的BeanDefinition

3、BeanDefinition继承的两个接口

3.1 BeanMetadataElement 接口

这个接口里只有一个方法:获取元数据元素的配置源代码对象。

3.2 AttributeAccessor 接口

这个接口定义了属性读取、设置的规范:

get/setAttribute 获取/设置属性

removeAttribute 移除属性

hasAttribute 判断是否存在属性

attributeNames 获取全部的属性

三、BeanDefinition简单应用

在Spring框架中,配置bean的方式有很多种,从最开始的xml文件,到现在的注解,有些bean是作为一个单独的bean被注册到容器里的,有些bean有父子关系,不同形式的bean对应的BeanDefinition对象也不同。但是从Spring2.5版本,默认使用的都是GenericBeanDefinition对象。

首先,封装两个简单的bean,其中一个bean依赖另一个bean。

import org.springframework.beans.factory.support.BeanDefinitionBuilder;import org.springframework.beans.factory.support.DefaultListableBeanFactory;import org.springframework.context.annotation.AnnotationConfigApplicationContext;class MyBean { // 依赖 DependencyBean private DependencyBean dependency;

public void setDependency(DependencyBean dependency) { this.dependency = dependency; }

public void doSomething() { if (dependency != null) { System.out.println("MyBean is doing something with dependency: " + dependency); } else { System.out.println("MyBean is doing something without dependency."); } }}

class DependencyBean { // Dependency bean code...}

接下来,测试代码:

/** * @author * @date * @Description BeanDefinition的简单应用 * */public class SpringApp { public static void main(String[] args) { // 1、创建ApplicationContext AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

// 2、获取BeanFactory DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory();

// 3、创建一个BeanDefinition BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(DependencyBean.class); // 4、注册BeanDefinition beanFactory.registerBeanDefinition("dependencyBean", beanDefinitionBuilder.getBeanDefinition()); // 打印dependencyBean的BeanDefinition对象 System.out.println(beanDefinitionBuilder.getBeanDefinition()); // 同 3 beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(MyBean.class); // 5、注册依赖 beanDefinitionBuilder.addPropertyReference("dependency", "dependencyBean");

// 同 4 注册BeanDefinition beanFactory.registerBeanDefinition("myBean", beanDefinitionBuilder.getBeanDefinition()); // 打印myBean的BeanDefinition对象 System.out.println(beanDefinitionBuilder.getBeanDefinition()); // 5、启动应用上下文 context.refresh();

// 6、获取Bean MyBean myBean = context.getBean(MyBean.class); myBean.doSomething();

// 7、关闭应用上下文 context.close(); }}

在上面示例中,首先创建Spring上下文,接着获取容器,然后使用构造器BeanDefinitionBuilder创建一个BeanDefinition,注册到容器里,接下来重复3、4、5,在3、4之间增加依赖,最后启用上下文,获取bean,执行bean中的方法。

运行结果:

从运行结果中,我们可以看到BeanDefinition对象是在容器中的bean实例化之前进行定义的,并且使用的是GenericBeanDefinition对象创建的BeanDefinition,在打印信息中,可以看到类的全部定义信息。

四、最后总结

1、Bean的类信息

Name:Bean的名称,我们通常使用这个名称来获取 Bean 的实例。例如,有一个名称为 “xxxService” 的 Bean,我们可以通过 context.getBean(“xxxService”) 来获取这个 Bean 的实例。

2、Bean的属性信息

Scope(作用域):Bean的作用域 singleton 或 prototype。如果 scope是singleton,那么Spring容器将只创建一个bean实例并在每次请求时返回这个实例。如果scope是prototyoe,那么每次请求bean时,Spring都将创建一个新的bean实例。

3、Bean的配置信息

Constructor arguments(构造函数参数):用于bean实例化的构造函数参数。如果我们有一个 Xxx 类,构造函数需要一个 String 类型的参数 name,那么我们可以在 BeanDefinition 中设置 constructor arguments 来提供这个参数。

Properties:需要注入到bean的属性值。例如,我们有一个 Xxx 类,它有一个String 类型的 name 属性,我们可以在 BeanDefinition 中设置 properties 来提供这个属性的值。也可以通标签或 @Value 注解在配置文件或类中注入。

4、Bean的行为特性

Lazy Initialization(懒加载):默认false,如果设置为true,bean将在首次请求时创建,而不是在应用启动时。这可以提高应用的启动速度,但可能会在首次请求bean时引入一些延迟。

Autowiring Mode:自动装配的模式。如果为byType,Spring容器将自动装配Bean的属性,查找容器中类型相匹配的bean并注入。如果为byName,容器将查找容器中名称匹配的bean并注入。还有一个选项是contructor,是指通过bean构造函数的参数类型来自动装配依赖。

Initialization Method and Destroy Method:bean的初始化和销毁方法。例如,有一个 XxxService 类,它有一个名为 init 的初始化方法和一个名为 cleanup 的销毁方法,我们可以在 BeanDefinition 中设置这两个方法,那么 Spring 容器将在创建 Bean 后调用 init 方法,在销毁 Bean 之前调用 cleanup 方法。

5、Bean的依赖关系

Dependency beans:Bean 的依赖关系。例如,有一个 XxxService Bean,它依赖于一个 XxxRepository Bean,可以在 XxxService 的 BeanDefinition 中设置 dependency beans 为 “xxxRepository”。在创建 XxxService Bean 之前,Spring 容器将首先创建 XxxRepository Bean。

BeanDefinition是Spring框架中用来描述Bean的元数据信息的接口,它定义了Bean的类名、作用域、构造函数参数、属性值、依赖关系等配置信息,是Spring IoC容器的核心概念之一。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/ObPaJuAqCJzh5w_pqteMAG-w0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券