Springboot扩展点系列_SmartInstantiationAwareBeanPostProcessor

功能特性

如下图为SmartInstantiationAwareBeanPostProcessor扩展点的UML类图,可以看出SmartInstantiationAwareBeanPostProcessor继承了InstantiationAwareBeanPostProcessor接口,而InstantiationAwareBeanPostProcessor接口又继承了BeanPostProcessor,对于InstantiationAwareBeanPostProcessor和BeanPostProcessor接口的功能特性、实现方式示例、工作原理在Springboot扩展点之InstantiationAwareBeanPostProcessor和Springboot扩展点之BeanPostProcessor两篇文章中都分别作了详细的分享,有兴趣的小伙们可以移步收藏+关注,而在本篇文章中着重分享SmartInstantiationAwareBeanPostProcessor接口独有的扩展方法。

img

1、SmartInstantiationAwareBeanPostProcesso接口有三个扩展点,分别是predictBeanType()、determineCandidateConstructors()、getEarlyBeanReference();

2、predictBeanType()用于在Bean实例化前预测最终返回的Class类型,触发时机是在InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()之前,如果不能预测,则返回null或正确的Class;如果预测一个错误的Class,那么程序就会报错了(举个例子:如果形参beanClass是Student.class,返回时改成了Teacher.class,报错是毫无疑问的;那么问题来了:这么预测的意义在哪?这一点我没有太明白,有知道的小伙伴告诉我一下哈);

3、determineCandidateConstructors()决定使用哪个构造器构造Bean,如果不指定,默认为null,即bean的无参构造方法;(感觉这个扩展点意义不大,实际上构造器分为两类:无参构造方法,有参数构造方法,无非有参数的构造方法参数至少一个以上,用哪种构造器来构造Bean我感觉区别不大,打个比方:用普通碗吃饭与用金碗吃饭,对一些人来说可能是有区别的,对我来说,吃饱就好了,什么碗我不在乎,哈哈,小伙们你觉得呢?)

4、getEarlyBeanReference()获得提前暴露的bean引用,主要用于Spring循环依赖问题的解决,如果Spring中检测不到循环依赖,这个方法不会被调用;当存在Spring循环依赖这种情况时,会在InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation方法触发执行之后执行;

public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
    //预测Bean的类型,返回第一个预测成功的Class类型,如果不能预测返回null;
    default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
      return null;
   }
    //决定使用哪个构造器构造Bean,如果不指定,默认为null,即bean的无参构造方法;
   default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
         throws BeansException {
 
      return null;
   }
    //获得提前暴露的bean引用,主要用于Spring循环依赖问题的解决;
   default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
      return bean;
   }
}

实现方式

Student.java

定义一个Student类,然后注入一个Teacher类;

@Slf4j
@Component
public class Student {
    private String name="xiao ming";
    @Autowired
    private Teacher teacher;
 
    public Student() {
        log.info("----student的无参数构造方法被执行");
    }
 
    public Student(String name) {
        this.name = name;
        log.info("----student的有参数构造方法被执行");
    }
 
    public Student(Teacher teacher) {
        this.teacher = teacher;
        log.info("----student的有参数构造方法(teacher)被执行");
    }
 
    public Student(String name, Teacher teacher) {
        this.name = name;
        this.teacher = teacher;
        log.info("----student的有参数构造方法(name,teacher)被执行");
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public Teacher getTeacher() {
        return teacher;
    }
 
    public void setTeacher(Teacher teacher) {
        log.info("----student中的setTeacher方法被调用");
        this.teacher = teacher;
    }
}

Teacher.java

定义一个Teacher类,然后给Teacher类注入一个Student类,这样Student类和Teacher类就形成了循环依赖,方便后面验验MySmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference执行情况;

@Component
@Slf4j
public class Teacher {
    private String name="li lao shi";
    @Autowired
    private Student student;
    public Teacher() {
        log.info("----teacher的无参数构造方法被执行");
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public Student getStudent() {
        return student;
    }
 
    public void setStudent(Student student) {
        log.info("----teacher中的setStudent方法被调用");
        this.student = student;
    }
}

MySmartInstantiationAwareBeanPostProcessor

定义MySmartInstantiationAwareBeanPostProcessor类,实现SmartInstantiationAwareBeanPostProcessor接口的predictBeanType方法、determineCandidateConstructors方法、getEarlyBeanReference方法、postProcessBeforeInstantiation方法;

@Component
@Slf4j
public class MySmartInstantiationAwareBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {
    @Override
    public Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("student")) {
            log.info("----predictBeanType方法被执行," + beanName);
            return Student.class;
        }
        return null;
    }
    //student类里是有四个构造方法,这里可以选择实际是两个:
    //一个无参数的构造方法,另一个是形参数是Teacher类型的
    @Override
    public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("student") ) {
            log.info("----determineCandidateConstructors方法被执行," + beanName);
            Constructor<?> constructor = beanClass.getConstructors()[3];
            Constructor<?>[] constructors={constructor};
            return constructors;
        }
        return null;
    }
 
    @Override
    public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
        if (beanName.equals("student") ) {
            log.info("----getEarlyBeanReference方法被执行," + beanName);
        }
        return bean;
    }
 
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("student")) {
            log.info("----postProcessBeforeInstantiation方法被执行,beanName:"+beanName);
            return null;
        }
        return null;
    }
}

单元测试验证

 @Component
@Slf4j
public class MySmartInstantiationAwareBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {
    @Override
    public Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("student")) {
            log.info("----predictBeanType方法被执行," + beanName);
            return Student.class;
        }
        return null;
    }
    //student类里是有四个构造方法,这里可以选择实际是两个:
    //一个无参数的构造方法,另一个是形参数是Teacher类型的
    @Override
    public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("student") ) {
            log.info("----determineCandidateConstructors方法被执行," + beanName);
            Constructor<?> constructor = beanClass.getConstructors()[3];
            Constructor<?>[] constructors={constructor};
            return constructors;
        }
        return null;
    }
 
    @Override
    public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
        if (beanName.equals("student") ) {
            log.info("----getEarlyBeanReference方法被执行," + beanName);
        }
        return bean;
    }
 
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("student")) {
            log.info("----postProcessBeforeInstantiation方法被执行,beanName:"+beanName);
            return null;
        }
        return null;
    } 
}

总结

以上内容就是Springboot的SmartInstantiationAwareBeanPostProcessor扩展点的全部内容,主要分享了功能特性和实现方式,之所以没有介绍其工作原理,是因为我发现,这个扩展点实际上很鸡肋,Spring的内部有使用,但是也很少,在实际业务开发中,很难用到,所以再长篇介绍其工作原理没有什么意义。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值