spring核心之BeanDefinition

Posted keep-go-on

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring核心之BeanDefinition相关的知识,希望对你有一定的参考价值。


什么是BeanDefinition ?

BeanDefinition顾名思义是spring的bean定义,spring创建bean时根据BeanDefinition的描述来创建bean,因此它是Spring的一个核心概念。

BeanDefinition有很多属性来描述bean :

  1. beanClass。它表示bean的类型。
  2. Scope,它表示bean的作用域。
  3. isLazy,表示bean是否需要懒加载。
  4. dependsOn,表示创建该bean时需要依赖其他bean。
  5. primary,表示bean为主bean。
  6. initMethod,表示bean的初始化方法。

beanClass

beanClass表示bean的类型,例如 : UserService.class、GroupController.class等,spring在创建bean时会根据该属性实例化对象。


Scope

scope属性表示bean的作用域,它有两个常见选项 singletonprototype

  1. singleton表示该bean是个单例bean(默认)。
  2. prototype表示该bean是个原型bean。

实际上官方说scope是有5个类型,singletonprototyperequestsessionglobal session。但是在ConfigurableBeanFactory中仅定义了 singletonprototype,因此最常见的属性其实就是单例和原型。

ConfigurableBeanFactory 中定义的scope类型

public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry 
    String SCOPE_SINGLETON = "singleton";
    String SCOPE_PROTOTYPE = "prototype";
 

单例bean

单例bean顾名思义就是使用单例模式创建的bean。该bean一旦被创建就会存在缓存中,后续任何对象调用该bean都不会创建新的bean实例,而是都使用这个对象。spring创建bean时默认就是采用单例模式。

原型bean

每次都会创建出新的对象,使用注解创建原型bean方法如下 :

@Component
@Scope("prototype")

spring的AbstractBeanFactory对象的doGetBean方法负责创建bean,到BeanFactory总结时会解析一下。

isLazy

isLazy表示bean是否需要懒加载:

首先原型bean上面已经说明了,是使用的时候创建新的实例,因此对于原型bean,isLazy不起作用。

对于单例bean,如果声明了需要懒加载,则在bean第一个被调用getBean时创建bean,如果不需要懒加载则在spring启动过程中初始化生成bean。

通常可以使用@Lazy注解来解决循环依赖的问题,但是循环依赖本身就该高耦合的表现,因此解决循环依赖还行建议遵循单一职责原则,在逻辑与结构上避免循环依赖

dependsOn

dependsOn表示在创建该bean时是需要依赖其他bean。在创建这个bean时其他依赖bean需要先创建完成。

primary

primary表示bean为主bean。spring中一个bean类型可以有多个bean实例,如果在进行依赖注入时,如果根据类型找到了多个bean,这时需要判断是否存在主bean,如果存在就直接将这个bean注入给属性,如果没有主bean就会抛出异常。

initMethodName

initMethodName表示bean的初始化方法,bean的生命周期中,有个步骤叫做bean的初始化,这个过程中会调用bean的initMethodName方法,我们在编写程序时可以通过指明该方法实现bean的初始化逻辑。


BeanDefinition的继承与实现关系

我们常用的@Bean@Componentbean标签等都会解析为BeanDefinition对象,然后在通过BeanFactory去创建Bean。

部分源码

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement 
	// 单例、原型标识符(其实远不止这两种)
	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

    // 标识 Bean 的类别,分别对应 用户定义的 Bean、来源于配置文件的 Bean、Spring 内部的 Bean
	int ROLE_APPLICATION = 0;
	int ROLE_SUPPORT = 1;
	int ROLE_INFRASTRUCTURE = 2;

    // 设置、返回 Bean 的父类名称
	void setParentName(@Nullable String parentName);
	String getParentName();

    // 设置、返回 Bean 的 className
	void setBeanClassName(@Nullable String beanClassName);
	String getBeanClassName();

    // 设置、返回 Bean 的作用域
	void setScope(@Nullable String scope);
	String getScope();

    // 设置、返回 Bean 是否懒加载
	void setLazyInit(boolean lazyInit);
	boolean isLazyInit();
	
	// 设置、返回当前 Bean 所依赖的其它 Bean 名称。
	void setDependsOn(@Nullable String... dependsOn);
	String[] getDependsOn();
	
	// 设置、返回 Bean 是否可以自动注入。只对 @Autowired 注解有效
	void setAutowireCandidate(boolean autowireCandidate);
	boolean isAutowireCandidate();
	
	// 设置、返回当前 Bean 是否为主要候选 Bean 。
	// 当同一个接口有多个实现类时,通过该属性来配置某个 Bean 为主候选 Bean。
	void setPrimary(boolean primary);
	boolean isPrimary();

    // 设置、返回创建该 Bean 的工厂类。
	void setFactoryBeanName(@Nullable String factoryBeanName);
	String getFactoryBeanName();
	
	// 设置、返回创建该 Bean 的工厂方法
	void setFactoryMethodName(@Nullable String factoryMethodName);
	String getFactoryMethodName();
	
	// 返回该 Bean 构造方法参数值、所有属性
	ConstructorArgumentValues getConstructorArgumentValues();
	MutablePropertyValues getPropertyValues();

    // 返回该 Bean 是否是单例、是否是非单例、是否是抽象的
	boolean isSingleton();
	boolean isPrototype();
	boolean isAbstract();

    // 返回 Bean 的类别。类别对应上面的三个属性值。
	int getRole();

以上是关于spring核心之BeanDefinition的主要内容,如果未能解决你的问题,请参考以下文章

[死磕 Spring 14/43] --- IOC 之注册解析的 BeanDefinition

Spring核心之BeanFactory 一张图看懂getBean全过程.

Spring核心之BeanFactory 一张图看懂getBean全过程.

spring源码阅读-- 容器启动之加载BeanDefinition

Spring之BeanDefinition详解

聊聊spring之贯穿全局的重要对象BeanDefinition