好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Spring IOC基于注解启动示例详析

spring 基于注解启动

主要有两个class实现注解启动

annotationconfigapplicationcontext annotationconfigwebapplicationcontext

我们以annotationconfigapplicationcontext 为研究对象


annotationconfigapplicationcontext.png

引入spring 最小依赖

?

1

2

3

4

5

<dependency>

  <groupid>org.springframework</groupid>

  <artifactid>spring-context</artifactid>

  <version>${spring.version}</version>

</dependency>

编写器启动代码

?

1

2

3

4

5

6

7

public static void main(string[] args) {

annotationconfigapplicationcontext applicationcontext = new annotationconfigapplicationcontext();

applicationcontext.register(beanconfig. class );

applicationcontext.refresh();

date date = applicationcontext.getbean( "date" ,date. class );

system.out.println(date);

}

annotationconfigapplicationcontext 构造函数

?

1

2

3

4

5

6

public annotationconfigapplicationcontext() {

    //负责注册class ,读取器

  this .reader = new annotatedbeandefinitionreader( this );

    //负责扫描指定类路径下的class,注册bean

  this .scanner = new classpathbeandefinitionscanner( this );

}

annotatedbeandefinitionreader 构造方法

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

public annotatedbeandefinitionreader(beandefinitionregistry registry) {

  this (registry, getorcreateenvironment(registry));

}

 

public annotatedbeandefinitionreader(beandefinitionregistry registry, environment environment) {

  assert .notnull(registry, "beandefinitionregistry must not be null" );

  assert .notnull(environment, "environment must not be null" );

  this .registry = registry;

    //初始化conditionevaluator

  this .conditionevaluator = new conditionevaluator(registry, environment, null );

    

  /** 在給定的注册表中註冊所有相关的post processors

   * 判断容器是否已经存在给定注册表的bean,如果没有注册bean,并将bean放入容器中

   * 把所有的处理处理器列出来

   * configurationclasspostprocessor 內部管理的配置注解处理器

   * autowiredannotationbeanpostprocessor 内部管理@autowired 的处理器

   * requiredannotationbeanpostprocessor @required的处理器

   * commonannotationbeanpostprocessor jsr-250注解处理器 ,先判断是否支持jsr,如果支持注册

   * persistenceannotationbeanpostprocessor jpa管理 先使用类加载器查找是否存在,如果有这个包则注册

   * eventlistenermethodprocessor @eventlistener的处理器

   * defaulteventlistenerfactory 管理eventlistenerfactory处理器

   */

  annotationconfigutils.registerannotationconfigprocessors( this .registry);

}

conditionevaluator 这个对象干什么,点击进去

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

public conditionevaluator( @nullable beandefinitionregistry registry,

   @nullable environment environment, @nullable resourceloader resourceloader) {

 

  this .context = new conditioncontextimpl(registry, environment, resourceloader);

}

  //conditioncontextimpl 实现了conditioncontext接口,conditionevaluator静态内部类

  public conditioncontextimpl( @nullable beandefinitionregistry registry,

    @nullable environment environment, @nullable resourceloader resourceloader) {

 

   this .registry = registry;

   this .beanfactory = deducebeanfactory(registry);

   this .environment = (environment != null ? environment : deduceenvironment(registry));

   this .resourceloader = (resourceloader != null ? resourceloader : deduceresourceloader(registry));

   this .classloader = deduceclassloader(resourceloader, this .beanfactory);

  }

可以知道conditionevaluator使用外部传参的方法初始化了spring容器顶级对象
beanfactory,environment,resourceloader,classloader。在将这些传给conditioncontextimpl为接下来的解析@conditional注解做好准备

classpathbeandefinitionscanner构造函数

?

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

public classpathbeandefinitionscanner(beandefinitionregistry registry) {

  this (registry, true );

}

 

public classpathbeandefinitionscanner(beandefinitionregistry registry, boolean usedefaultfilters) {

  this (registry, usedefaultfilters, getorcreateenvironment(registry));

}

 

public classpathbeandefinitionscanner(beandefinitionregistry registry, boolean usedefaultfilters,

   environment environment) {

  this (registry, usedefaultfilters, environment,

    (registry instanceof resourceloader ? (resourceloader) registry : null ));

}

 

public classpathbeandefinitionscanner(beandefinitionregistry registry, boolean usedefaultfilters,

   environment environment, @nullable resourceloader resourceloader) {

  assert .notnull(registry, "beandefinitionregistry must not be null" );

  this .registry = registry;

  if (usedefaultfilters) {

   registerdefaultfilters();

  }

  setenvironment(environment);

  setresourceloader(resourceloader);

}

 

protected void registerdefaultfilters() {

  this .includefilters.add( new annotationtypefilter(component. class ));

  classloader cl = classpathscanningcandidatecomponentprovider. class .getclassloader();

  try {

   this .includefilters.add( new annotationtypefilter(

     (( class <? extends annotation>) classutils.forname( "javax.annotation.managedbean" , cl)), false ));

   logger.debug( "jsr-250 'javax.annotation.managedbean' found and supported for component scanning" );

  }

  catch (classnotfoundexception ex) {

  }

  try {

   this .includefilters.add( new annotationtypefilter(

     (( class <? extends annotation>) classutils.forname( "javax.inject.named" , cl)), false ));

   logger.debug( "jsr-330 'javax.inject.named' annotation found and supported for component scanning" );

  }

  catch (classnotfoundexception ex) {

   // jsr-330 api not available - simply skip.

  }

}

绕了地球几圈了,其实就是将spring 顶级接口 environment,resourceloader赋值,使用默认注解过滤器,首先将@component加入list中,判断当前环境是否支持jsr-250,jsr-330,相应加入过滤器中。也就是这个扫描器默认只扫描@component或者jsr-250,jsr-330的标记的class。

applicationcontext.register(beanconfig.class)

?

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

public void register( class <?>... annotatedclasses) {

   assert .notempty(annotatedclasses, "at least one annotated class must be specified" );

   this .reader.register(annotatedclasses); //调用 刚刚初始化读取器

  }

            |

============================annotatedbeandefinitionreader 读取器代码======================================================================================================

   public void register( class <?>... annotatedclasses) {

   for ( class <?> annotatedclass : annotatedclasses) {

    registerbean(annotatedclass);

   }

   }

 

  public void registerbean( class <?> annotatedclass) {

   doregisterbean(annotatedclass, null , null , null );

  }

  

  /**

  *从给定的bean解析class给定的注解,执行相应的初始化,保存到spring容器中

  */

  <t> void doregisterbean( class <t> annotatedclass, @nullable supplier<t> instancesupplier, @nullable string name,

    @nullable class <? extends annotation>[] qualifiers, beandefinitioncustomizer... definitioncustomizers) {

 

   //根据class的annotated 得出元数据 annotationmetadata

   annotatedgenericbeandefinition abd = new annotatedgenericbeandefinition(annotatedclass);

   /**

   * 判断注册的class 是否包含@conditional注解,如果有获取全部value,放入list中

   * 排序后,遍历所有的conditiion的实现,使用反射获取对象,执行matches方法,

   * 如果发现有返回false,中断循环直接返回true,

   */

   if ( this .conditionevaluator.shouldskip(abd.getmetadata())) { //如果 @conditional条件不满足,不进行注册

    return ;

   }

 

   abd.setinstancesupplier(instancesupplier);

   //解析class是否有@scope,解析@scope注解返回scopemetadata对象,没有直接返回空

   scopemetadata scopemetadata = this .scopemetadataresolver.resolvescopemetadata(abd);

   abd.setscope(scopemetadata.getscopename());

   //判断注解上value是否有值,有就使用这个作为beanname,没有则取类名

   string beanname = (name != null ? name : this .beannamegenerator.generatebeanname(abd, this .registry));

   //继续解析annotationmetadata的@lazy,@primary,@dependson,@role,@description的注解,放入结果放入对象的属性中

   annotationconfigutils.processcommondefinitionannotations(abd);

   //这个类只是beandefinition 包装类

   beandefinitionholder definitionholder = new beandefinitionholder(abd, beanname);

   //是否需要代理类,如果是则修改内部属性,重新生成beandefinition 对象

   definitionholder = annotationconfigutils.applyscopedproxymode(scopemetadata, definitionholder, this .registry);

   //调用defaultlistablebeanfactory.registerbeandefinition的方法,做一些安全性校验再,将definitionholder 放入register容器中

   beandefinitionreaderutils.registerbeandefinition(definitionholder, this .registry);

  }

这个方法就是将注册的bean,解析class上的注解,初始化注解数据,做相应处理,转化成beandefinition ,放入spring 容器中保存起来。

我们看下beandefinition是怎么实现注册到spring的容器中,主要由defaultlistablebeanfactory.registerbeandefinition来实现

?

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

public void registerbeandefinition(string beanname, beandefinition beandefinition)

    throws beandefinitionstoreexception {

 

   assert .hastext(beanname, "bean name must not be empty" );

   assert .notnull(beandefinition, "beandefinition must not be null" );

 

   if (beandefinition instanceof abstractbeandefinition) {

    try {

     //对beandefinition 进行校验判断methodoverrides不能为空,必须拥有工厂方法

     ((abstractbeandefinition) beandefinition).validate();

    }

    catch (beandefinitionvalidationexception ex) {

     throw new beandefinitionstoreexception(beandefinition.getresourcedescription(), beanname,

       "validation of bean definition failed" , ex);

    }

   }

 

   beandefinition oldbeandefinition;

 

   oldbeandefinition = this .beandefinitionmap.get(beanname);

   if (oldbeandefinition != null ) {

     //这个方法是判断是否允许出现重名bean,并且是不同的定义bean,是否可以覆盖前者

    if (!isallowbeandefinitionoverriding()) {

     throw new beandefinitionstoreexception(beandefinition.getresourcedescription(), beanname,

       "cannot register bean definition [" + beandefinition + "] for bean '" + beanname +

       "': there is already [" + oldbeandefinition + "] bound." );

    }

    else if (oldbeandefinition.getrole() < beandefinition.getrole()) {

     // e.g. was role_application, now overriding with role_support or role_infrastructure

     if ( this .logger.iswarnenabled()) {

      this .logger.warn( "overriding user-defined bean definition for bean '" + beanname +

        "' with a framework-generated bean definition: replacing [" +

        oldbeandefinition + "] with [" + beandefinition + "]" );

     }

    }

    else if (!beandefinition.equals(oldbeandefinition)) {

     if ( this .logger.isinfoenabled()) {

      this .logger.info( "overriding bean definition for bean '" + beanname +

        "' with a different definition: replacing [" + oldbeandefinition +

        "] with [" + beandefinition + "]" );

     }

    }

    else {

     if ( this .logger.isdebugenabled()) {

      this .logger.debug( "overriding bean definition for bean '" + beanname +

        "' with an equivalent definition: replacing [" + oldbeandefinition +

        "] with [" + beandefinition + "]" );

     }

    }

    this .beandefinitionmap.put(beanname, beandefinition);

   }

   else {

    //调用alreadycreated.isempty(),alreadycreated set对象,保存已经创建beanname

    //文档中表示created,跟这里注册应该不是同一个行为,这个要看到后面才知道什么意思

    if (hasbeancreationstarted()) {

     synchronized ( this .beandefinitionmap) { //更新数据

      this .beandefinitionmap.put(beanname, beandefinition);

      list<string> updateddefinitions = new arraylist<>( this .beandefinitionnames.size() + 1 );

      updateddefinitions.addall( this .beandefinitionnames);

      updateddefinitions.add(beanname);

      this .beandefinitionnames = updateddefinitions;

      if ( this .manualsingletonnames.contains(beanname)) {

       set<string> updatedsingletons = new linkedhashset<>( this .manualsingletonnames);

       updatedsingletons.remove(beanname);

       this .manualsingletonnames = updatedsingletons;

      }

     }

    }

    else {

     //spring beandefinition 容器,一个map转载

     this .beandefinitionmap.put(beanname, beandefinition);

     //保存beanname,主要用于记录每个bean注册顺序

     this .beandefinitionnames.add(beanname);

     //删除单例,注册成一个普通bean

     this .manualsingletonnames.remove(beanname);

    }

    this .frozenbeandefinitionnames = null ;

   }

 

   if (oldbeandefinition != null || containssingleton(beanname)) {

    //更新spring容器里beanname

    resetbeandefinition(beanname);

   }

  }

将beandefinition注册到spring容器中,并没有太多复杂的逻辑,只是做一些安全性的检查。

beandefinition

一个beandefinition描述了一个bean的实例,包括属性值,构造方法参数值和继承自它的类的更多信息。beandefinition仅仅是一个最简单的接口,主要功能是允许beanfactorypostprocessor 例如propertyplaceholderconfigure 能够检索并修改属性值和别的bean的元数据(译注)

spring 容器beandefinition主要分为rootbeandefinition,annotatedgenericbeandefinition这两种

rootbeandefinition     spring factory中的特定bean annotatedgenericbeandefinition      用户自定义bean

spring 启动流程总结

annotationconfigapplicationcontext 初始化.png

这些beandefinition只是放入到spirng 容器中,并没有进行任何初始化对象的操作,真正的ioc操作都在refresh(),这个方法有空再进行分析。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。

原文链接:https://HdhCmsTestjianshu测试数据/p/573bdae020e9

查看更多关于Spring IOC基于注解启动示例详析的详细内容...

  阅读:16次