InstantiationAwareBeanPostProcessor接口解析,dubbo中的应用

409 阅读3分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

说到Bean的实例化,就不得不提一下InstantiationAwareBeanPostProcessor接口。 InstantiationAwareBeanPostProcessor继承自BeanPostProcessor接口。

InstantiationtiationAwareBeanPostProcessor接口的方法介绍:

1.postProcessBeforeInstantiation方法是最先执行的方法,它在目标对象实例化之前调用,该方法的返回值类型是Object,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走

2.postProcessAfterInstantiation方法在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。因为它的返回值是决定要不要调用postProcessPropertyValues方法的其中一个因素(因为还有一个因素是mbd.getDependencyCheck());如果该方法返回false,并且不需要check,那么postProcessPropertyValues就会被忽略不执行;如果返回true,postProcessPropertyValues就会被执行

3.postProcessPropertyValues方法对属性值进行修改(这个时候属性值还未被设置,但是我们可以修改原本该设置进去的属性值)。如果postProcessAfterInstantiation方法返回false,该方法可能不会被调用。可以在该方法内对属性值进行修改。

BeanPostProcessor接口方法介绍:

1.postProcessBeforeInitialization方法是在bean初始化方法调用之前执行此方法。

2.postProcessAfterInitialization方法是在init-method方法执行之后执行。

在dubbo框架中的应用

dubbo服务的消费者,会引用服务提供方的接口,这个接口的实现类对象是通过动态代理生成的,其生成和注入的过程是正是利用了spring的InstantiationAwareBeanPostProcessor接口。

在AnnotationInjectedBeanPostProcessor类中,重写了postProcessPropertyValues()方法。对@Reference注解标注的属性,进行了赋值。

我们先写一个dubbo的服务的消费者。

@Service
public class ConsumerServiceImpl  implements ConsumerService{

    @Reference(check = false)
    private AService aService;

    @Override
    public void invokeDubboApi(){

        aService.test();

    }
}

下面解析下源码,看下aService是如何赋值的。

@Override
public PropertyValues postProcessPropertyValues(
        PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
    //获取需要注入的属性和方法元数据
    InjectionMetadata metadata = findInjectionMetadata(beanName, bean.getClass(), pvs);
    try {
        //注入属性值
        metadata.inject(bean, beanName, pvs);
    } catch (BeanCreationException ex) {
        throw ex;
    } catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of @" + getAnnotationType().getSimpleName()
                + " dependencies is failed", ex);
    }
    return pvs;
}

对于标注了@Reference注解的属性来说,使用如下代码进行属性值的注入:

public class AnnotatedFieldElement extends InjectionMetadata.InjectedElement {

    private final Field field;

    private final AnnotationAttributes attributes;

    private volatile Object bean;

    protected AnnotatedFieldElement(Field field, AnnotationAttributes attributes) {
        super(field, null);
        this.field = field;
        this.attributes = attributes;
    }

    @Override
    protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {

        Class<?> injectedType = field.getType();
        //代理对象
        Object injectedObject = getInjectedObject(attributes, bean, beanName, injectedType, this);

        ReflectionUtils.makeAccessible(field);
        //对属性赋值
        field.set(bean, injectedObject);

    }

}

inject方法很简单,就是先获取dubbo服务生产者的代理对象,然后利用反射进行赋值。

代理对象的生成详解,我将在下一篇文章中进行解说。

最后谢谢大家的支持,喜欢的话,请点赞关注哦。