一前言

正如我们所熟悉的,spring 是一个“大型的工厂”,在这个工厂中会产生一个个的实例,这些实例可以是单例的、非单例的。
工厂中的实例,也就是这次我们要进行分析的对象,BeanDefinition。
可以认为Spring中管理的所有对象,这些对象都是BeanDefinition.

二、类图分析

我们先看一下类图:
image.png
我们重点关注一下BeanDefinition,它是一个接口,并且继承了BeanMetadataElement,AttributeAccessor.
先分析一下这个类的关系

2.1、BeanMetadataElement

  1. public interface BeanMetadataElement {
  2. Object getSource();//返回对象的元数据
  3. }

这里边所讲的元数据,可以理解为一个对象实例。

2.2、AttributeAccessor

  1. public interface AttributeAccessor {
  2. void setAttribute(String name, Object value);
  3. Object getAttribute(String name);
  4. Object removeAttribute(String name);
  5. boolean hasAttribute(String name);
  6. String[] attributeNames();
  7. }

根据方法的命名,我们可以看出,这些方法都是对对象实例的操作。

2.3、BeanDefinition

  1. public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
  2. //代码 不粘了
  3. }

看一下类的结构图:
image.png

这个类,主要提供了一些对象的读取信息,和一些基本的设置信息。(比如类是不是单例啊、)
总结一下,BeanMetadataElement提供对象元数据,AttributeAccessor只对对象的属性进行读取和设置,BeanDefinition拥有了这两个接口的功能以外,还有读取类的基本信息的功能。

它完成了BeanDefinition的大部分工作,当然它也预留了一些我们必须要重写的方法:

需要子类实现的方法

  1. cloneBeanDefinition(): 克隆方法
  2. getParentName():获取当前Bean的父类
  3. setParentName():设置当前Bean的父类

三、抽象实现:AbstractBeanDefinition

14-Spring源码扩展-BeanDefinition详解 - 图4

再来看AbstractBeanDefinition这个类,从名字中可以看出,它是一个模板抽象类。BeanDefinition 中只是定义了一系列的 get/set方法,并没有提供对应的属性,在 AbstractBeanDefinition 中将所有的属性定义出来了。该抽象类下有个三个子类:GenericBeanDefinition、RootBeanDefinition、ChildBeanDefinition。我们先来看AbstractBeanDefinition本身的一些方法与属性。

  1. public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
  2. implements BeanDefinition, Cloneable {
  3. //默认作用域名称的常量:等效于单例
  4. public static final String SCOPE_DEFAULT = "";
  5. //自动装配的一些常量
  6. // autowireMode = 0,默认值,未激活Autowiring。
  7. // bean 标签的 autowire 属性值为 no
  8. // 1、在xml中需要手动指定依赖注入对象 配置 property标签或者 constructor-arg标签
  9. // 2、使用 @Autowired 注解,autowireMode 的值也是 0
  10. public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;
  11. //autowireMode = 1,根据set方法的的名称作为Bean名称进行依赖查找
  12. //(去掉set,并尝试将首字母变为小写),并将对象设置到该set方法的参数上
  13. // bean 标签的 autowire 属性值配置为 byName
  14. public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
  15. //autowireMode = 2,根据set方法参数的类型作为Bean类型进行依赖查找
  16. //并将对象设置到该set方法的参数上
  17. // bean 标签的 autowire 属性值配置为 byType
  18. public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
  19. //autowireMode = 3,构造器注入
  20. // bean 标签的 autowire 属性值配置为 constructor
  21. public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
  22. //表明通过Bean的class的内部来自动装配 Spring3.0被弃用。
  23. // bean 标签的 autowire 属性值配置为 autodetect
  24. @Deprecated
  25. public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
  26. //检查依赖是否合法,在本类中,默认不进行依赖检查
  27. //不进行检查
  28. public static final int DEPENDENCY_CHECK_NONE = 0;
  29. //对对象引用进行依赖性检查
  30. public static final int DEPENDENCY_CHECK_OBJECTS = 1;
  31. //对“简单”属性进行依赖性检查
  32. public static final int DEPENDENCY_CHECK_SIMPLE = 2;
  33. //对所有属性进行依赖检查
  34. public static final int DEPENDENCY_CHECK_ALL = 3;
  35. //若Bean未指定销毁方法,容器应该尝试推断Bean的销毁方法的名字,
  36. //目前,推断的销毁方法的名字一般为close或是shutdown
  37. public static final String INFER_METHOD = "(inferred)";
  38. //Bean的class对象或是类的全限定名
  39. @Nullable
  40. private volatile Object beanClass;
  41. //默认的scope是单例,对应bean属性scope
  42. //@Scope
  43. @Nullable
  44. private String scope = SCOPE_DEFAULT;
  45. //是否是抽象,对应bean属性abstract
  46. private boolean abstractFlag = false;
  47. //是否懒加载,对应bean属性lazy-init,默认不是懒加载
  48. //@Lazy
  49. @Nullable
  50. private Boolean lazyInit;
  51. //自动注入模式,对应bean属性autowire,默认不进行自动装配
  52. private int autowireMode = AUTOWIRE_NO;
  53. //是否进行依赖检查,默认不进行依赖检查
  54. private int dependencyCheck = DEPENDENCY_CHECK_NONE;
  55. //用来表示一个bean的实例化是否依靠另一个bean的实例化,先加载dependsOn的bean,
  56. //对应bean属性depend-on
  57. //@DependsOn
  58. @Nullable
  59. private String[] dependsOn;
  60. /**
  61. * autowire-candidate属性设置为false,这样容器在查找自动装配对象时,
  62. * 将不考虑该bean,即它不会被考虑作为其他bean自动装配的候选者,
  63. * 但是该bean本身还是可以使用自动装配来注入其他bean的
  64. */
  65. private boolean autowireCandidate = true;
  66. /**
  67. * 自动装配时出现多个bean候选者时,将作为首选者,对应bean属性primary,默认不是首选的
  68. * @Primary
  69. */
  70. private boolean primary = false;
  71. /**
  72. * 用于记录Qualifier,对应子元素qualifier <bean><qualifier></qualifier></bean>
  73. * 如果容器中有多个相同类型的 bean,这时我们就可以使用qualifier属性来设置加载指定Bean名称的bean
  74. * @Qualifier
  75. */
  76. private final Map < String, AutowireCandidateQualifier > qualifiers = new LinkedHashMap <>();
  77. //java8的函数式接口,创建bean实例的方式之一
  78. @Nullable
  79. private Supplier <? > instanceSupplier;
  80. //是否允许访问非public方法和属性, 默认是true
  81. private boolean nonPublicAccessAllowed = true;
  82. }

3.1、GenericBeanDefinition

GenericBeanDefinition是spring2.5之后才有的,这个的想法是用来替代RootBeanDefinition/ChildBeanDefinition,而RootBeanDefinition/ChildBeanDefinition可以在spring预加载的时候使用。

那我们主要关注一下GenericBeanDefinition这个类。

  1. public class GenericBeanDefinition extends AbstractBeanDefinition {
  2. private String parentName;
  3. /**
  4. * 创建GenericBeanDefinition之后,可以通过一下方法对bean的属性进行配置
  5. */
  6. public GenericBeanDefinition() {
  7. super();
  8. }
  9. public GenericBeanDefinition(BeanDefinition original) {
  10. super(original);
  11. }
  12. @Override
  13. public void setParentName(String parentName) {
  14. this.parentName = parentName;
  15. }
  16. @Override
  17. public String getParentName() {
  18. return this.parentName;
  19. }
  20. @Override
  21. public AbstractBeanDefinition cloneBeanDefinition() {
  22. return new GenericBeanDefinition(this);
  23. }
  24. //其他代码省略
  25. }

通过代码分析,我们现在就可以创建一个spring可以使用的bean了:

  1. public class SringApp {
  2. @Data
  3. static class Bean {
  4. String name;
  5. int age;
  6. }
  7. public static void main(String[] args) {
  8. AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
  9. GenericBeanDefinition definition = new GenericBeanDefinition();
  10. definition.setBeanClass(Bean.class);
  11. definition.getPropertyValues().add("name", "xiaoli");
  12. definition.getPropertyValues().add("age", 1);
  13. // 注册.
  14. context.registerBeanDefinition("bean1", definition);
  15. context.refresh();
  16. Bean bean = (Bean) context.getBean("bean1");
  17. System.out.println(bean);
  18. }
  19. }

GenericBeanDefinition其实还可以继承的

  1. public static void main(String[] args) {
  2. AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
  3. GenericBeanDefinition definition = new GenericBeanDefinition();
  4. definition.setBeanClass(Bean.class);
  5. definition.getPropertyValues().add("name", "xiaoli");
  6. definition.getPropertyValues().add("age", 1);
  7. context.registerBeanDefinition("bean1", definition);
  8. GenericBeanDefinition definition2 = new GenericBeanDefinition();
  9. definition2.setParentName("bean1");
  10. // bean2 的属性继承了 bean1
  11. context.registerBeanDefinition("bean2", definition2);
  12. context.refresh();
  13. Bean bean1 = (Bean) context.getBean("bean1");
  14. Bean bean2 = (Bean) context.getBean("bean2");
  15. // 虽然是这样,但是返回的false. 因为只是继承了属性.
  16. System.out.println(bean1==bean2);
  17. }

3.2、RootBeanDefinition 和 ChildBeanDefinition

RootBeanDefinition 这是一个最常用的实现类,Spirng 去创建 Bean 时是基于RootBeanDefinition去创建的!

RootBeanDefinition继承了AbstractBeanDefinition,在AbstractBeanDefinition的基础上扩展了一些之外的功能,并且RootBeanDefinition是没有父BeanDefinition的。

RootBeanDefinition 和 ChildBeanDefinition这俩成双成对的。root节点不能有父类 , 其中儿子节点, 必须有父类 . 用法上和上面那个没啥区别.

  1. public static void main(String[] args) {
  2. AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
  3. // root
  4. RootBeanDefinition definition = new RootBeanDefinition();
  5. definition.setBeanClass(Bean.class);
  6. definition.getPropertyValues().add("name", "xiaoli");
  7. definition.getPropertyValues().add("age", 1);
  8. context.registerBeanDefinition("bean1", definition);
  9. // child
  10. ChildBeanDefinition definition2 = new ChildBeanDefinition("bean1");
  11. context.registerBeanDefinition("bean2", definition2);
  12. // 刷新
  13. context.refresh();
  14. Bean bean1 = (Bean) context.getBean("bean1");
  15. Bean bean2 = (Bean) context.getBean("bean2");
  16. System.out.println(bean1==bean2);
  17. }

3.3、BeanDefinitionBuilder 工具

很显然就是一个Builder的工具类.

  1. BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(Bean.class);
  2. // lazy 的意思是. 你需要(调用get("beanname")方法)的时候才要实例化.
  3. builder.setLazyInit(true);
  4. // builder.getBeanDefinition() 其实是一个 GenericBeanDefinition
  5. context.registerBeanDefinition("bean3", builder.getBeanDefinition());

四、AnnotatedBeanDefinition

image.png

  1. public interface AnnotatedBeanDefinition extends BeanDefinition {
  2. AnnotationMetadata getMetadata();
  3. MethodMetadata getFactoryMethodMetadata();
  4. }

BeanDefinition的另一个扩展,就是枚举相关的AnnotatedBeanDefinition。当然这个扩展是从spring 2.5之后才有的。

4.1、子接口:AnnotatedGenericBeanDefinition

14-Spring源码扩展-BeanDefinition详解 - 图6
AnnotatedGenericBeanDefinitionAnnotatedBeanDefinition的一个具体实现。传入指定类后,可以获取类中的注解:

  1. public class Test {
  2. public static void main(String[] args) throws Exception {
  3. AnnotatedGenericBeanDefinition genericBeanDefinition = new AnnotatedGenericBeanDefinition(Person.class);
  4. genericBeanDefinition.setBeanClassName("springBean");
  5. genericBeanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);
  6. genericBeanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
  7. // genericBeanDefinition.setPropertyValues();给属性添加值
  8. System.out.println(genericBeanDefinition.getMetadata().getAnnotationTypes());
  9. }
  10. @TT
  11. class Person{
  12. }
  13. @Target(ElementType.TYPE)
  14. @Retention(RetentionPolicy.RUNTIME)
  15. public @interface TT{
  16. }
  17. }

输出:

  1. [Test$TT]

4.2、ScannedGenericBeanDefinition


ScannedGenericBeanDefinition是AnnotatedBeanDefinition的另一个实现,与AnnotatedGenericBeanDefinition不同的是,ScannedGenericBeanDefinition是通过扫描 class,然后操作 asm进行解析的。
除此之外,其他是一样的。以后我们再来讨论关于asm相关的知识。