加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

spring中BeanPostProcessor之一:InstantiationAwareBeanPostPro

发布时间:2020-12-15 01:14:26 所属栏目:大数据 来源:网络整理
导读:在上篇博客中写道了bean后置处理器InstantiationAwareBeanPostProcessor,只介绍了其中一个方法的作用及用法,现在来看postProcessBeforeInstantiation方法。 一、概述 postProcessBeforeInstantiation方法定义在InstantiationAwareBeanPostProcessor接口中

在上篇博客中写道了bean后置处理器InstantiationAwareBeanPostProcessor,只介绍了其中一个方法的作用及用法,现在来看postProcessBeforeInstantiation方法。

一、概述

postProcessBeforeInstantiation方法定义在InstantiationAwareBeanPostProcessor接口中,方法的定义如下,

@Nullable
    default Object postProcessBeforeInstantiation(Class<?> beanClass,String beanName) throws BeansException {
        return null;
    }

从上面的代码中可以看到该方法默认返回null。

二、详述

postProcessBeforeInstantiation方法是用来做什么的,在看源码的过程中,在createBean方法中找到了该方法的调用,下面只贴出相关代码,

try {
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            1、调用beanPostProcessor即bean的后置处理器,这里会调用2次后置处理器
            Object bean = resolveBeforeInstantiation(beanName,mbdToUse);
            if (bean != ) {
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(),beanName,"BeanPostProcessor before instantiation of bean failed",ex);
        }

在resolveBeforeInstantiation方法中进行了调用,resolveBeforeInstantiation方法返回值如果不为null,则该方法直接返回bean,也就是说resolveBeforeInstantiation方法至关重要,下面是resolveBeforeInstantiation方法,

protected Object resolveBeforeInstantiation(String beanName,RootBeanDefinition mbd) {
        Object bean = ;
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
             Make sure bean class is actually resolved at this point.
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                Class<?> targetType = determineTargetType(beanName,mbd);
                if (targetType != ) {
                    如果是InstantiationAwareBeanPostProcessor的实例,则执行其postProcessBeforeInstantiation方法
                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType,beanName);
                    如果上面的postProcessBeforeInstantiation方法返回值不为null,则执行所有beanPostProcessor的postProcessAfterInitialization方法
                    bean不为null,则说明postProcesBeforeInstantiation方法中的返回值是一个不为null的对象
                    ) {
                        bean = applyBeanPostProcessorsAfterInitialization(bean,beanName);
                    }
                }
            }
            mbd.beforeInstantiationResolved = (bean != );
        }
         bean;
    }

在resolveBeforeInstantiation方法中首先调用了applyBeanPostProcessorsBeforeInstantiation方法,该方法中便会调用InstantiationAwareBeanPostProcessor接口中的postProcessBeforeInstantiation方法,且如果applyBeanPostPorcessorsBeforeInstantiation方法返回值不为null,才会调用applyBeanPostProcessAfterIntialization方法,下面先看applyBeanPostProcessorsBeforeInstantiation方法

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass,String beanName) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                Object result = ibp.postProcessBeforeInstantiation(beanClass,beanName);
                if (result !=  result;
                }
            }
        }
        ;
    }

从上面方法的定义看到,该方法会遍历benaFactory中的beanPostProcessor,并且判断是否为InstantiationAwareBeanPostPrecessor的类型,如果是执行其postProcessBeforeInstantiation方法,这里默认注册的beanPostProcessor该方法的返回值均为null。稍后自定义一个BeanPostProcessor实现InstantiationAwareBeanPostProcessor接口。

下面看applyBeanPostProcessAfterIntializtion方法,

@Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean,String beanName)
             BeansException {

        Object result = existingBean;
         (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result,beanName);
            if (current ==  result;
            }
            result = current;
        }
         result;
    }

改方法的逻辑是遍历beanFactory中的所有的beanPostProcessor,执行其postProcessAfterInitialization方法,该方法定义在BeanPostProcessor接口中,默认返回bean,如下,

default Object postProcessAfterInitialization(Object bean,1)"> bean;
    }

从上面可以看出默认返回的是bean参数的值,也就是如果该方法未实现则默认返回参数中的bean。

再次回到resolveBeforeInstantiation方法,再看其逻辑有以下几种方法返回值的组合,

1、applyBeanPostProcessBeforeInstantiation返回值为null,则resolveBeforeInstantiation方法返回null;

2、applyBeanPostProcessBeforeInstantiation返回值bean不为null,applyBeanPostProcessAfterInitialization方法返回值为null,则resolveBeforeInstantiationf方法返回值为bean;

3、applyBeanPostProcessBeforeInstantiation返回值bean不为null,applyBeanPostProcessAfterInitialization方法返回值bean1不为为null,则resolveBeforeInstantiationf方法返回值为bean1;

从resolveBeforeInstantiation方法分析,该方法的返回值,直接决定了createBean方法的返回值,也就是说applyBeanPostProcessBeforeInstantiation方法返回的bean不为null,下面的方法不会执行。

再来看调用resolveBeforeInstantiation方法时的注释

 Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName,mbdToUse);

大体意思时给BeanPostProcessor一个机会返回代理对象而不是目标对象的实例,所以这里resolveBeforeInstantiation方法返回的必然时一个代理对象(JDK和CGLib)。看下面的例子

自定义的BeanPostProcessor实现了InstantiationAwareBeanPostProcessor

package cn.com.my.test;

import org.springframework.beans.BeansException;
 org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
 org.springframework.stereotype.Component;

 net.sf.cglib.proxy.Enhancer;
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean,1)"> TODO Auto-generated method stub
        
        if("userService".equals(beanName)) {
            
            UserService us=(UserService)bean;
            
            Enhancer enhancer =  Enhancer();
            设置目标类的字节码文件
            enhancer.setSuperclass(UserService.class);
            设置回调函数
            enhancer.setCallback( MyMethodInterceptor());
            
            这里的creat方法就是正式创建代理类
            UserService proxyUs = (UserService)enhancer.create();
             proxyUs;
        }
        return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInitialization(bean,beanName);
    }
}

当beanName等于userUservice时返回的是经过cglib代理后的对象。在MyInstantiationAwareBeanPostProcessor类中仅实现了postProcessBeforeInitialization方法,未实现postProcessAfterInitialization方法,所以resolveBeforeInstantiation方法的返回值即未postProcessBeforeInitialization方法的返回值,在上面的类中就是使用cglib代理后的UserService实例。

代理类MyMethodInterceptor,实现cglib的MethodInterceptor接口

 java.lang.reflect.Method;

 org.springframework.cglib.proxy.MethodProxy;

 net.sf.cglib.proxy.MethodInterceptor;

class MyMethodInterceptor  MethodInterceptor{

   
    @Override
     Object intercept(Object arg0,Method arg1,Object[] arg2,net.sf.cglib.proxy.MethodProxy arg3)
             Throwable {
         TODO Auto-generated method stub
         Object object = arg3.invokeSuper(arg0,arg2);
          object;
    }  
}

下面是测试类

 org.springframework.context.annotation.AnnotationConfigApplicationContext;

 Test {

    static void main(String[] args) {
         TODO Auto-generated method stub

        AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(Config.);
        
        UserService us=ac.getBean(UserService.);
        System.out.println("us:"+us);
        
    }

}

看下面的结果,

us:cn.com.my.test.UserService$$EnhancerByCGLIB$$ffa582b4@5fe94a96

返回的是UserService的一个经过cglib代理后的对象。到这里发现真好强大,返回的一个代理对象。

三、适用场合

实现InstantiationAwareBeanPostProcessor接口的postProcessBeforeInitialization方法,通过返回一个代理对象的方式,达到改变目标类类型的目的。在不想改变现有类的逻辑而又想借助现有类实现其他功能,就可以使用这种方式。像AOP就是这种实现,AnnotationAwareAspectJAutoProxyCreator类便是InstantiationAwareBeanPostProcessor的一个实现。

?

原创不易,有不当之处,欢迎指正,谢谢!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读