评论

收藏

[Java] spring BeanProcessor接口详解

编程语言 编程语言 发布于:2021-08-31 12:44 | 阅读数:298 | 评论:0

这篇文章主要介绍了spring BeanProcessor接口的相关资料,帮助大家更好的理解和学习使用spring,感兴趣的朋友可以了解下
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实例化前后执行。
DSC0000.jpg

我们先定义一个beanprocessor接口实现类和一个instantiationawarebeanpostprocessor接口实现类。
beanpostprocessor实现类:
//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实现类:
//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对象:
//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加载进去:
@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版本)。
DSC0001.jpg

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
@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
@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
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;
  }
 
}
代码调用
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()开始看起:
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():
//abstractapplicationcontext#registerbeanpostprocessors
protected void registerbeanpostprocessors(configurablelistablebeanfactory beanfactory) {
  //委托给postprocessorregistrationdelegate.registerbeanpostprocessors进行处理
  postprocessorregistrationdelegate.registerbeanpostprocessors进行处理(beanfactory, this);
}
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接口的资料请关注CodeAE代码之家其它相关文章!
原文链接:https://juejin.cn/post/6844904196026843149

关注下面的标签,发现更多相似文章