zoukankan      html  css  js  c++  java
  • spring中BeanPostProcessor之一:InstantiationAwareBeanPostProcessor(02)

    在上篇博客中写道了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 != null) {
                    return bean;
                }
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                        "BeanPostProcessor before instantiation of bean failed", ex);
            }

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

    @Nullable
        protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
            Object bean = null;
            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 != null) {
                        //如果是InstantiationAwareBeanPostProcessor的实例,则执行其postProcessBeforeInstantiation方法
                        bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                        //如果上面的postProcessBeforeInstantiation方法返回值不为null,则执行所有beanPostProcessor的postProcessAfterInitialization方法
                        //bean不为null,则说明postProcesBeforeInstantiation方法中的返回值是一个不为null的对象
                        if (bean != null) {
                            bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                        }
                    }
                }
                mbd.beforeInstantiationResolved = (bean != null);
            }
            return bean;
        }

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

    @Nullable
        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 != null) {
                        return result;
                    }
                }
            }
            return null;
        }

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

    下面看applyBeanPostProcessAfterIntializtion方法,

    @Override
        public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
                throws BeansException {
    
            Object result = existingBean;
            for (BeanPostProcessor processor : getBeanPostProcessors()) {
                Object current = processor.postProcessAfterInitialization(result, beanName);
                if (current == null) {
                    return result;
                }
                result = current;
            }
            return result;
        }

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

    @Nullable
        default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            return 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;
    import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
    import org.springframework.stereotype.Component;
    
    import net.sf.cglib.proxy.Enhancer;
    @Component
    public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            // TODO Auto-generated method stub
            
            if("userService".equals(beanName)) {
                
                UserService us=(UserService)bean;
                
                Enhancer enhancer = new Enhancer();
                //设置目标类的字节码文件
                enhancer.setSuperclass(UserService.class);
                //设置回调函数
                enhancer.setCallback(new MyMethodInterceptor());
                
                //这里的creat方法就是正式创建代理类
                UserService proxyUs = (UserService)enhancer.create();
                return proxyUs;
            }
            return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
        }
    }

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

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

    package cn.com.my.test;
    
    import java.lang.reflect.Method;
    
    import org.springframework.cglib.proxy.MethodProxy;
    
    import net.sf.cglib.proxy.MethodInterceptor;
    
    public class MyMethodInterceptor implements MethodInterceptor{
    
       
        @Override
        public Object intercept(Object arg0, Method arg1, Object[] arg2, net.sf.cglib.proxy.MethodProxy arg3)
                throws Throwable {
            // TODO Auto-generated method stub
             Object object = arg3.invokeSuper(arg0, arg2);
             return object;
        }  
    }

    下面是测试类

    package cn.com.my.test;
    
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    public class Test {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
    
            AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(Config.class);
            
            UserService us=ac.getBean(UserService.class);
            System.out.println("us:"+us);
            
        }
    
    }

    看下面的结果,

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

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

    三、适用场合

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

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

  • 相关阅读:
    接口interface
    枚举类型
    编写Hello World ts程序
    TypeScript基本类型
    初始TypeScript
    session和cookie自动登录机制
    奇辉机车车号自动识别系统介绍
    AForge.NET 设置摄像头分辨率
    工作感概—活到老xio到老
    Scala学习二十二——定界延续
  • 原文地址:https://www.cnblogs.com/teach/p/12642349.html
Copyright © 2011-2022 走看看