复盘一下spring学习-基础了解
spring基础1 - BeanFactory
BeanFactory,以Factory结尾,表示它是一个工厂类(接口), 它负责生产和管理bean的一个工厂。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。BeanFactory只是个接口,并不是IOC容器的具体实现,但是Spring容器给出了很多种实现,如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等,其中XmlBeanFactory就是常用的一个,该实现将以XML方式描述组成应用的对象及对象间的依赖关系。XmlBeanFactory类将持有此XML配置元数据,并用它来构建一个完全可配置的系统或应用。
BeanFactory是用于访问Spring Bean容器的根接口,是一个单纯的Bean工厂,也就是常说的IOC容器的顶层定义,各种IOC容器是在其基础上为了满足不同需求而扩展的,包括经常使用的ApplicationContext
在Spring容器启动的过程中,会将类解析成Spring内部的BeanDefinition结构,并将BeanDefinition存储到一个叫DefaultListableBeanFactory中,DefaultListableBeanFactory是整个Bean加载的核心部分,是Spring注册及加载Bean的默认实现。下面列出了DefaultListableBeanFactory源代码中两个重要的属性:
/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
/** List of bean definition names, in registration order */
private volatile List<String> beanDefinitionNames = new ArrayList<String>(256);
其中,bean的定义被解析成 BeanDefinition,同时解析得到 beanName,将beanName和BeanDefinition存储到beanDefinitionMap中,同时会将beanName存储到beanDefinitionNames中。
spring基础2 - BeanDefinition
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
String SCOPE_SINGLETON = "singleton";
String SCOPE_PROTOTYPE = "prototype";
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
}
先看看BeanDefinition 代码结构,是一个接口,并包含BeanMetadataElement -> getSource 元数据,类似一个来源之类的东西,而AttributeAccessor是一个配置属性工具。
BeanDefinition是bean在spring中的描述,有了BeanDefinition我们就可以创建Bean,BeanDefinition是Bean在spring
中的定义形态 接下来我们看看BeanDefinition的相关接口与类.
方法
String: getBeanClassName: 返回当前bean definition定义的类名
ConstructorArgumentValues: getConstructorArgumentValues:返回bean的构造函数参数
String[]: getDependsOn:返回当前bean所依赖的其他bean的名称
String: getFactoryBeanName: 返回factory bean的名称
String: getFactoryMethodName: 返回工厂方法的名称
BeanDefinition: getOriginatingBeanDefinition: 返回原始的BeanDefinition,如果不存在返回null
String: getParentName: 返回当前bean definition的父definition的名字
MutablePropertyValues: getPropertyValues: 返回一个用于新的bean实例上的属性值
String: getScope: 返回当前bean的目标范围
boolean: isAbstract: 当前bean是否是abstract,意味着不能被实例化
boolean: isLazyInit: bean是否是延迟初始化
boolean: isPrimary: bean是否为自动装配的主要候选bean
boolean: isPrototype: bean是否是多实例
boolean: isSingleton: bean是否是单例
void: setAutowiredCandidate(boolean): 设置bean是否对其他bean是自动装配的候选bean
void: setBeanClassName(String): 指定bean definition的类名
void: setDependsOn(String …): 设置当前bean初始化所依赖的beans的名称
void: setFactoryBeanName(String): 如果factory bean的名称
void: setFactoryMethodName(String): 设置工厂的方法名
void: setLazyInit(boolean lazyInit): 设置是否延迟初始化
void: setParentName(String): 设置父definition的名称
void: setPrimary(boolean): 设置是否主要的候选bean
void: setScope(String): 设置bean的范围,如:单例,多实例
2-1 AnnotatedBeanDefinition
AnnotatedBeanDefinition 是 BeanDefinition 子接口之一,该接口扩展了 BeanDefinition 的功能,其用来操作注解元数据。一般情况下,通过注解方式得到的 Bean(@Component、@Bean),其 BeanDefinition 类型都是该接口的实现类。
public interface AnnotatedBeanDefinition extends BeanDefinition {
// 获得当前 Bean 的注解元数据
AnnotationMetadata getMetadata();
// 获得当前 Bean 的工厂方法上的元数据
MethodMetadata getFactoryMethodMetadata();
}
该接口可以返回两个元数据的类:
AnnotationMetadata:主要对 Bean 的注解信息进行操作,如:获取当前 Bean 标注的所有注解、判断是否包含指定注解。
MethodMetadata:方法的元数据类。提供获取方法名称、此方法所属类的全类名、是否是抽象方法、判断是否是静态方法、判断是否是final方法等。
2-2 AbstractBeanDefinition
AbstractBeanDefinition 是 BeanDefinition 的子抽象类,也是其他 BeanDefinition 类型的基类,其实现了接口中定义的一系列操作方法,并定义了一系列的常量属性,这些常量会直接影响到 Spring 实例化 Bean 时的策略。核心属性如下。
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable{
...
}
AbstractBeanDefinition 中定义的一些常量和属性,并且还有一部分是操作这些属性的 set 和 get 方法,这些方法都由子类来操作,且应用程序中真正使用的也是这些子类 BeanDefinition。
先来看 AbstractBeanDefinition 直接实现类:RootBeanDefinition、GenericBeanDefinition、ChildBeanDefinition。
2-2-1 RootBeanDefinition
该类继承自 AbstractBeanDefinition,它可以单独作为一个 BeanDefinition,也可以作为其他 BeanDefinition 的父类。
RootBeanDefinition 在 AbstractBeanDefinition 的基础上定义了更多属性。
2-2-2 ChildBeanDefinition
该类继承自 AbstractBeanDefinition。其相当于一个子类,不可以单独存在,必须依赖一个父 BeanDetintion,构造 ChildBeanDefinition 时,通过构造方法传入父 BeanDetintion 的名称或通过 setParentName 设置父名称。它可以从父类继承方法参数、属性值,并可以重写父类的方法,同时也可以增加新的属性或者方法。若重新定义 init 方法,destroy 方法或者静态工厂方法,ChildBeanDefinition 会重写父类的设置。从 Spring 2.5 开始,以编程方式注册 Bean 定义的首选方法是 GenericBeanDefinition,GenericBeanDefinition 可以有效替代 ChildBeanDefinition 的绝大分部使用场合
2-2-3 GenericBeanDefinition
GenericBeanDefinition 是 Spring 2.5 以后新引入的 BeanDefinition,是 ChildBeanDefinition 更好的替代者,它同样可以通过 setParentName 方法设置父 BeanDefinition。
最后三个 BeanDefinition 既实现了 AnnotatedBeanDefinition 接口,又间接继承 AbstractBeanDefinition 抽象类,这些 BeanDefinition 描述的都是注解形式的 Bean。
2-2-4 ConfigurationClassBeanDefinition
该类继承自 RootBeanDefinition ,并实现了 AnnotatedBeanDefinition 接口。这个 BeanDefinition 用来描述在标注 @Configuration 注解的类中,通过 @Bean 注解实例化的 Bean。
其功能特点如下:
1、如果 @Bean 注解没有指定 Bean 的名字,默认会用方法的名字命名 Bean。
2、标注 @Configuration 注解的类会成为一个工厂类,而标注 @Bean 注解的方法会成为工厂方法,通过工厂方法实例化 Bean,而不是直接通过构造方法初始化。
3、标注 @Bean 注解的类会使用构造方法自动装配
2-2-5 AnnotatedGenericBeanDefinition
该类继承自 GenericBeanDefinition ,并实现了 AnnotatedBeanDefinition 接口。这个 BeanDefinition 用来描述标注 @Configuration 注解的 Bean。
2-2-6 ScannedGenericBeanDefinition
该类继承自 GenericBeanDefinition ,并实现了 AnnotatedBeanDefinition 接口。这个 BeanDefinition 用来描述标注 @Component 注解的 Bean,其派生注解如 @Service、@Controller 也同理。
总结
最后,我们来做个总结。BeanDefinition 主要是用来描述 Bean,其存储了 Bean 的相关信息,Spring 实例化 Bean 时需读取该 Bean 对应的 BeanDefinition。BeanDefinition 整体可以分为两类,一类是描述通用的 Bean,还有一类是描述注解形式的 Bean。一般前者在 XML 时期定义 <bean‘> 标签以及在 Spring 内部使用较多,而现今我们大都使用后者,通过注解形式加载 Bean。