好得很程序员自学网

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

spring BeanProcessor接口详解

1. 简单认识beanprocessor

beanprocessor的理解

beanprocessor是spring中的一个重要接口,他有两个接口方法一个是postprocessbeforeinitialization前置初始化,另一个是postprocessafterinitialization后置初始化。从名称上就可以大概清楚这个接口的作用:在一个业务流程的前后加入两个接口方法,当执行这个业务流程时,就会触发这两个接口方法的执行。简单的总结一下有两个要点:

在业务流程中,根据beanprocessor接口方法加在不同的位置(一般是前后),可以实现对业务逻辑的扩展。 在业务逻辑执行前,beanprocessor的实现类必须已经被创建完成(beanprocessor接口类必须要优先实例化)。

而在spring中,就有很多实现了beanprocessor的bean,通过在重要的业务流程(如bean的生命周期流程)的前后加上beanprocessor接口方法,就可以对业务逻辑进行修改或补充。

一个beanprocessor的使用实例

在spring的bean生命周期中,beanprocessor接口方法会在bean创建后的初始化方法(init-method或@postconstruct指向的方法)前后执行before和after方法;那有没有在bean创建前后执行的接口方法呢?答案是肯定有的,这个功能是由beanprocessor的子接口instantiationawarebeanpostprocessor来实现的,他也是有before和after方法,会在bean实例化前后执行。

我们先定义一个beanprocessor接口实现类和一个instantiationawarebeanpostprocessor接口实现类。

beanpostprocessor实现类:

?

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

//net.postprocessor.customerpostprocessor

@component

public class customerpostprocessor implements beanpostprocessor {

 

   @postconstruct

   public void init(){

    system.out.println( "执行customerpostprocessor的postconstruct" );

   }

 

   public customerpostprocessor(){

    system.out.println( "执行customerpostprocessor的构造方法" );

   }

 

   @override

   public object postprocessbeforeinitialization(object bean, string beanname) throws beansexception {

    system.out.println(bean+ "======beforeinitialization======" + beanname);

    return bean;

   }

 

   @override

   public object postprocessafterinitialization(object bean, string beanname) throws beansexception {

    system.out.println(bean+ "======afterinitialization======" + beanname);

    return bean;

   }

 

}

instantiationawarebeanpostprocessor实现类:

?

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

//net.postprocessor.customerinitialpostprocessor

@component

public class customerinitialpostprocessor implements instantiationawarebeanpostprocessor {

 

   @postconstruct

   public void init(){

    system.out.println( "执行customerinitialpostprocessor的postconstruct" );

   }

 

   public customerinitialpostprocessor(){

    system.out.println( "执行customerinitialpostprocessor的构造方法" );

   }

 

   @override

   public object postprocessbeforeinstantiation( class <?> beanclass, string beanname) throws beansexception {

    system.out.println( "bean初始化前执行:class为" +beanclass.getname()+ "|beanname为" +beanname);

    return null ;

   }

 

   @override

   public boolean postprocessafterinstantiation(object bean, string beanname) throws beansexception {

    system.out.println( "bean初始化后执行:object为" +bean+ "|beanname为" +beanname);

    return false ;

   }

}

再创建一个普通的bean对象:

?

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

//net.postprocessor.firstbean

@component

public class firstbean implements initializingbean {

 

   private string msg = "hello" ;

 

   @postconstruct

   public void init(){

    system.out.println( "执行firstbean的postconstruct" );

   }

 

   public firstbean(){

    system.out.println( "firstbean构造方法!" +msg);

   }

 

   public string getmsg() {

    return msg;

   }

 

   public void setmsg(string msg) {

    this .msg = msg;

   }

 

   @override

   public void afterpropertiesset() throws exception {

    system.out.println( "执行firstbean的afterpropertiesset" );

   }

}

我们创建一个spring工厂对象将上述bean加载进去:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

@test

public void test(){

   annotationconfigapplicationcontext applicationcontext = new annotationconfigapplicationcontext( "net.postprocessor" );

}

//执行得到以下结果:

执行customerinitialpostprocessor的构造方法

执行customerinitialpostprocessor的postconstruct

执行customerpostprocessor的构造方法

执行customerpostprocessor的postconstruct

  

bean初始化前执行: class 为net.postprocessor.firstbean|beanname为firstbean

firstbean构造方法!hello

bean初始化后执行:object为net.postprocessor.firstbean @79179359 |beanname为firstbean

  

net.postprocessor.firstbean @79179359 ======beforeinitialization======firstbean

执行firstbean的postconstruct

执行firstbean的afterpropertiesset

net.postprocessor.firstbean @79179359 ======afterinitialization======firstbean

通过上述结果证明了我们之前的说法是正确的:

1.beanpostprocessor接口类会优先实例化,且在实例化中无法不会调用beanpostprocessor接口方法的

2.instantiationawarebeanpostprocessor接口方法会在firstbean构造方法构造方法前后执行

3.beanpostprocessor接口方法会在firstbean实例化后进行初始化的前后执行

注意:若@postconstruct注解方法方法未执行,请加入javax.annotation:javax.annotation-api:1.3.2jar包依赖,原因是@postconstruct是j2ee标准的注解,不是spring自己的接口,而在jdk8往上的版本中设计者打算弃用这些注解,所以做了处理,我们是没有办法直接使用j2ee标准注解的(@resource、@postconstruct、@predestroy等几个注解),为了兼容这种情况,所以有了javax.annotation-apijar包的产生(或者降低jdk版本)。

2. beanprocessor的实现思路和简化实例

beanprocessor大概的实现思路

通过之前的了解beanprocessor的使用,我们可以知道beanprocessor并不复杂,但是却十分的重要,下面来分析下beanprocessor的实现思路:

创建个接口a,接口包含一些切点方法(before、after、around之类的),实现这个接口a的类要在使用前就创建好 我们需要有个业务流程,这个业务流程由若干步组成;将接口a的接口方法插入到这些业务步骤之间(需要扩展的地方) 要执行这个业务流程时,把接口a的实现类对象赋值到业务流程中,在执行业务流程中,就会触发接口方法的执行完成功能扩展

当我们更换赋值到业务流程中的接口a的实现类时,对应的扩展逻辑也会随之变化,这样就实现了可插拔式的扩展逻辑(策略模式)。

一个beanprocessor的简化逻辑实例

在spring中我们可以创建任意数量的bean实现beanprocessor接口,所以实际上我们是要一个全局的beanprocessorlist对象用来存储这些beanprocessor对象;在执行业务代码时,要循环这个beanprocessorlist对象,获取你需要的beanprocessor对象来执行接口方法。下面是一个模拟spring bean生命周期的简化版,来帮助你理解spring中beanprocessor的工作原理。

net.postprocessor.secondbean.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

@component

public class secondbean {

 

   private string msg = "world" ;

 

   public secondbean(){

    system.out.println( "secondbean构造方法!" +msg);

   }

 

   public string getmsg() {

    return msg;

   }

 

   public void setmsg(string msg) {

    this .msg = msg;

   }

}

net.postprocessor.customerpostprocessor.java

?

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

@component

public class customerpostprocessor implements beanpostprocessor {

 

   @postconstruct

   public void init(){

    system.out.println( "执行customerpostprocessor的postconstruct" );

   }

 

   public customerpostprocessor(){

    system.out.println( "执行customerpostprocessor的构造方法" );

   }

 

   @override

   public object postprocessbeforeinitialization(object bean, string beanname) throws beansexception {

    system.out.println(bean+ "======beforeinitialization======" + beanname);

    return bean;

   }

 

   @override

   public object postprocessafterinitialization(object bean, string beanname) throws beansexception {

    system.out.println(bean+ "======afterinitialization======" + beanname);

    return bean;

   }

 

}

net.postprocessor.postprocessor.java

?

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

85

86

87

88

public class postprocessor {

 

   //模拟扫描到的bean信息<"secondbean", "net.postprocessor.secondbean">

   map<string, string> scanbeanmap = new hashmap<>();

 

   //模拟spring的beanpostprocessors列表

   list<beanpostprocessor> processorbeanlist = new arraylist<>();

 

   //模拟bean对象缓存

   map<string, object> beancache = new hashmap<>();

 

   //添加扫描的bean信息

   public postprocessor addbeaninfo(string beanname, string classpath){

    this .scanbeanmap.put(beanname, classpath);

    return this ;

   }

 

   //模拟bean创建流程

   public object execute(){

    try {

      //先临时存储实现了postprocessor接口的bean对象

      list<beanpostprocessor> postprocessorstrlist = new arraylist<>();

      //循环scanbeanmap,获取bean列表中实现了postprocessor接口的类,加入processorbeanlist中

      for (string temp: scanbeanmap.keyset()){

       class <?> clazz = class .forname(scanbeanmap.get(temp));

       //判断是否实现了beanpostprocessor接口

       if (beanpostprocessor. class .isassignablefrom(clazz)){

         //实例化让如临时容器

         postprocessorstrlist.add((beanpostprocessor)createbean(temp));

       }

      }

      //将实现了postprocessor接口的bean加入processorbeanlist中

      for (beanpostprocessor obj: postprocessorstrlist){

       processorbeanlist.add(obj);

      }

 

      //再次循环scanbeanmap初始化所用bean

      for (string temp: scanbeanmap.keyset()){

       createbean(temp);

      }

 

    } catch (classnotfoundexception e) {

      e.printstacktrace();

    }

    return null ;

   }

 

   //bean实例化

   public object createbean(string beanname){

    //从缓存中获取

    if (beancache.containskey(beanname)){

      return beancache.get(beanname);

    } else {

      //缓存中取不到,则进行创建后加入缓存

      try {

       class <?> clazz = class .forname(scanbeanmap.get(beanname));

       //processor前置方法执行

       for (beanpostprocessor processor : processorbeanlist){

         processor.postprocessbeforeinitialization(clazz, beanname);

       }

 

       //bean实例化

       object result = clazz.getconstructor().newinstance();

 

       //processor后置方法执行

       for (beanpostprocessor processor : processorbeanlist){

         processor.postprocessafterinitialization(result, beanname);

       }

 

       //将bean加入缓存

       beancache.put(beanname, result);

       return result;

      } catch (classnotfoundexception e) {

       e.printstacktrace();

      } catch (illegalaccessexception e) {

       e.printstacktrace();

      } catch (instantiationexception e) {

       e.printstacktrace();

      } catch (nosuchmethodexception e) {

       e.printstacktrace();

      } catch (invocationtargetexception e){

       e.printstacktrace();

      }

    }

    return null ;

   }

 

}

代码调用

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

public static void main(string[] args) {

   postprocessor postprocessor = new postprocessor();

   //添加扫描到的bean

   postprocessor

   .addbeaninfo( "secondbean" , "net.postprocessor.secondbean" )

   .addbeaninfo( "customerpostprocessor" , "net.postprocessor.customerpostprocessor" );

   postprocessor.execute();

}

 

//执行结果

执行customerpostprocessor的构造方法

class net.postprocessor.secondbean======beforeinitialization======secondbean

secondbean构造方法!world

net.postprocessor.secondbean @1b40d5f0 ======afterinitialization======secondbean

代码逻辑如下:

循环bean信息列表,将beanpostprocessor接口bean分离出来优先实例化(实例化中缓存bean对象),并将之放入临时容器。 循环完成,将临时容器中的beanpostprocessor接口bean赋值到全局beanpostprocessor接口列表中 再次循环bean信息列表,缓存存在则直接返回缓存对象,不存在则进行bean实例化,期间循环调用全局beanpostprocessor接口对象方法

3. spring中beanprocessor的源码解析

我们要从spring中的refresh()开始看起:

?

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

public void refresh() throws beansexception, illegalstateexception {

   synchronized ( this .startupshutdownmonitor) {

    // prepare this context for refreshing.

    //刷新准备

    preparerefresh();

 

    // tell the subclass to refresh the internal bean factory.

    //告诉子类刷新内部bean工厂。

    configurablelistablebeanfactory beanfactory = obtainfreshbeanfactory();

 

    // prepare the bean factory for use in this context.

    //为容器准备bean工程

    preparebeanfactory(beanfactory);

 

    try {

      // allows post-processing of the bean factory in context subclasses.

      //允许在上下文bean的后处理工厂子类。

      postprocessbeanfactory(beanfactory);

 

      // invoke factory processors registered as beans in the context.

      //优先将beandefinitionregistrypostprocessor\beanfactorypostprocessor接口的bean对象实例化

      //属于spring内部组件调用

      invokebeanfactorypostprocessors(beanfactory);

 

      // register bean processors that intercept bean creation.

      //处理用户自定义postprocessor接口对象,之后加入spring的beanpostprocessors列表,

      // 供之后预实例化其他bean时触发这些postprocessor方法

      registerbeanpostprocessors(beanfactory);

 

         //...省略代码

     //实例化所有(non-lazy-init)单件。

         finishbeanfactoryinitialization(beanfactory);

    }

 

    catch (beansexception ex) {

      if (logger.iswarnenabled()) {

       logger.warn( "exception encountered during context initialization - " +

          "cancelling refresh attempt: " + ex);

      }

 

      // destroy already created singletons to avoid dangling resources.

      //bean销毁

      destroybeans();

 

      // reset 'active' flag.

      //取消刷新

      cancelrefresh(ex);

 

      // propagate exception to caller.

      throw ex;

    }

 

    finally {

      // reset common introspection caches in spring's core, since we

      // might not ever need metadata for singleton beans anymore...

      //重置公共缓存

      resetcommoncaches();

    }

   }

}

其中包含有postprocess字段都有可能和beanprocessor相关,这里有三个相关方法:

postprocessbeanfactory(beanfactory),这个是一共空的扩展方法,显然无关 invokebeanfactorypostprocessors(beanfactory),处理spring中实现了beanprocessor接口的内部组件直接调用接口方法 registerbeanpostprocessors(beanfactory),实例化用户自定义beanprocessor接口bean组件,之后循环赋值到全局beanprocessor列表中

所以registerbeanpostprocessors()就是我们要找的对象,来跟进看下registerbeanpostprocessors():

?

1

2

3

4

5

//abstractapplicationcontext#registerbeanpostprocessors

protected void registerbeanpostprocessors(configurablelistablebeanfactory beanfactory) {

   //委托给postprocessorregistrationdelegate.registerbeanpostprocessors进行处理

     postprocessorregistrationdelegate.registerbeanpostprocessors进行处理(beanfactory, this );

}

?

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

public static void registerbeanpostprocessors(

    configurablelistablebeanfactory beanfactory, abstractapplicationcontext applicationcontext) {

 

   //查询实现了beanpostprocessor接口的beanname

   string[] postprocessornames = beanfactory.getbeannamesfortype(beanpostprocessor. class , true , false );

 

   // register beanpostprocessorchecker that logs an info message when

   // a bean is created during beanpostprocessor instantiation, i.e. when

   // a bean is not eligible for getting processed by all beanpostprocessors.

   int beanprocessortargetcount = beanfactory.getbeanpostprocessorcount() + 1 + postprocessornames.length;

   beanfactory.addbeanpostprocessor( new beanpostprocessorchecker(beanfactory, beanprocessortargetcount));

 

   // separate between beanpostprocessors that implement priorityordered,

   // ordered, and the rest.

   list<beanpostprocessor> priorityorderedpostprocessors = new arraylist<>();

   list<beanpostprocessor> internalpostprocessors = new arraylist<>();

   list<string> orderedpostprocessornames = new arraylist<>();

   list<string> nonorderedpostprocessornames = new arraylist<>();

   //根据beanname循环调用getbean进行实例化

   for (string ppname : postprocessornames) {

    if (beanfactory.istypematch(ppname, priorityordered. class )) {

      beanpostprocessor pp = beanfactory.getbean(ppname, beanpostprocessor. class );

      priorityorderedpostprocessors.add(pp);

      if (pp instanceof mergedbeandefinitionpostprocessor) {

       internalpostprocessors.add(pp);

      }

    }

    else if (beanfactory.istypematch(ppname, ordered. class )) {

      orderedpostprocessornames.add(ppname);

    }

    else {

      nonorderedpostprocessornames.add(ppname);

    }

   }

 

   // first, register the beanpostprocessors that implement priorityordered.

   //对beanpostprocessor接口对象进行排序

   sortpostprocessors(priorityorderedpostprocessors, beanfactory);

   //将获取到的postprocessors接口对象加入到spring的beanpostprocessors列表

   registerbeanpostprocessors(beanfactory, priorityorderedpostprocessors);

 

   // next, register the beanpostprocessors that implement ordered.

   list<beanpostprocessor> orderedpostprocessors = new arraylist<>();

   for (string ppname : orderedpostprocessornames) {

    beanpostprocessor pp = beanfactory.getbean(ppname, beanpostprocessor. class );

    orderedpostprocessors.add(pp);

    if (pp instanceof mergedbeandefinitionpostprocessor) {

      internalpostprocessors.add(pp);

    }

   }

   sortpostprocessors(orderedpostprocessors, beanfactory);

   registerbeanpostprocessors(beanfactory, orderedpostprocessors);

 

   // now, register all regular beanpostprocessors.

   list<beanpostprocessor> nonorderedpostprocessors = new arraylist<>();

   for (string ppname : nonorderedpostprocessornames) {

    beanpostprocessor pp = beanfactory.getbean(ppname, beanpostprocessor. class );

    nonorderedpostprocessors.add(pp);

    if (pp instanceof mergedbeandefinitionpostprocessor) {

      internalpostprocessors.add(pp);

    }

   }

   registerbeanpostprocessors(beanfactory, nonorderedpostprocessors);

 

   // finally, re-register all internal beanpostprocessors.

   sortpostprocessors(internalpostprocessors, beanfactory);

   registerbeanpostprocessors(beanfactory, internalpostprocessors);

 

   // re-register post-processor for detecting inner beans as applicationlisteners,

   // moving it to the end of the processor chain (for picking up proxies etc).

   beanfactory.addbeanpostprocessor( new applicationlistenerdetector(applicationcontext));

}

果然这里就是处理beanpostprocessor接口的地方,逻辑和之前的思路类似:

循环扫描到的bean列表,获取实现了beanpostprocessor接口的beanname数组 循环beanname数组数组,调用beanfactory.getbean()将bean实例化,并放入priorityorderedpostprocessors列表中 调用sortpostprocessors对priorityorderedpostprocessors列表进行排序(处理beanpostprocessor调用的顺序) 调用registerbeanpostprocessors将priorityorderedpostprocessors列表中的bean对象赋值到全局列表beanpostprocessors中 回到refresh()中,当调用finishbeanfactoryinitialization()对所用bean进行预实例化时就会调用这些beanpostprocessor接口方法

以上就是spring beanprocessor接口详解的详细内容,更多关于spring beanprocessor接口的资料请关注其它相关文章!

原文链接:https://juejin.cn/post/6844904196026843149

查看更多关于spring BeanProcessor接口详解的详细内容...

  阅读:15次