Spring浅谈:AOP初始化过程

| 分类 java之web开发  java之web框架  | 标签 java  spring  切面  面向切面编程  AOP  AspectJ  面向切面  编译  装饰器设计模式  声明式事务  IoC  IoC容器  spring-context  spring-aspects  pom  Maven  后置处理器  BeanFactoryAware  SmartInstantiationAwareBeanPostProcessor  AnnotationAwareAspectJAutoProxyCreator  增强器  切入点表达式 

Spring源码解析

上一章展示了AOP 的运行效果,大概展示了AOP 的功能是如何集成到Spring 框架中的,本文来看一下被切面的类在运行时刻的一些原理和现象!

上一章讲到,@EnableAspectJAutoProxy 为IoC 容器注入了AnnotationAwareAspectJAutoProxyCreator 这个Bean。再次将这个Bean 的继承关系列一下

AnnotationAwareAspectJAutoProxyCreator
    extends AspectJAwareAdvisorAutoProxyCreator
        extends AbstractAdvisorAutoProxyCreator
            extends AbstractAutoProxyCreator
                extends ProxyProcessorSupport
                implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware

前面几篇讲道理PostProcessor、Aware,这里重点看一下AbstractAutoProxyCreator 实现这两个接口的方法

实现Aware 的接口是AbstractAutoProxyCreator.setBeanFactory(),实现为当前的类注入BeanFactory

Spring浅谈:Aware接口相关

@Override
public void setBeanFactory(BeanFactory beanFactory) {
    this.beanFactory = beanFactory;
}

再看实现SmartInstantiationAwareBeanPostProcessor 的接口,方便拦截Bean 的创建过程,实现在各个Bean 的初始化前后对其做一些定制化的加工

Spring浅谈:后置处理器PostProcessor

@Override
public Object postProcessBeforeInstantiation(Class<> beanClass, String beanName) throws BeansException {
    Object cacheKey = getCacheKey(beanClass, beanName);

    if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
        if (this.advisedBeans.containsKey(cacheKey)) {
            return null;
        }
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }

    // Create proxy here if we have a custom TargetSource.
    // Suppresses unnecessary default instantiation of the target bean:
    // The TargetSource will handle target instances in a custom fashion.
    if (beanName != null) {
        TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
        if (targetSource != null) {
            this.targetSourcedBeans.add(beanName);
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
            Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }
    }

    return null;
}

@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) {
    return true;
}

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
    return bean;
}

/**
 * Create a proxy with the configured interceptors if the bean is
 * identified as one to proxy by the subclass.
 * @see #getAdvicesAndAdvisorsForBean
 */
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

更进一步的看一下这个继承树

AnnotationAwareAspectJAutoProxyCreator
    extends AspectJAwareAdvisorAutoProxyCreator
        extends AbstractAdvisorAutoProxyCreator
            extends AbstractAutoProxyCreator
                extends ProxyProcessorSupport
                implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware

从父类开始往上看,每个类分别实现了哪些功能,结合Aware、PostProcessor 的工作原理弄清楚这些类的执行时机和调用关系

  • AbstractAutoProxyCreator 实现了这些方法
    • BeanFactoryAware.setBeanFactory()
    • SmartInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
    • SmartInstantiationAwareBeanPostProcessor.postProcessAfterInitialization()
  • AbstractAdvisorAutoProxyCreator 重写了这些方法
    • BeanFactoryAware.setBeanFactory() 内部调用了initBeanFactory()
  • AspectJAwareAdvisorAutoProxyCreator
  • AnnotationAwareAspectJAutoProxyCreator
    • 实现了initBeanFactory() 方法
    • 上面说到是在AbstractAdvisorAutoProxyCreator.setBeanFactory() 中调用的

经过上面的梳理,大概可以弄清楚从父类到子类分别实现了哪些接口,分别实现了哪些方法,对应的调用关系也差不多清楚了

Spring浅谈:Aware接口相关

Spring浅谈:后置处理器PostProcessor

上面列过了AbstractAutoProxyCreator 这个类实现了Aware、PostProcessor 的接口的代码,下面看看另外的一些

AbstractAdvisorAutoProxyCreator 重写的setBeanFactory()

@Override
public void setBeanFactory(BeanFactory beanFactory) {
    super.setBeanFactory(beanFactory);
    if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
        throw new IllegalArgumentException(
                "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
    }
    initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}

AnnotationAwareAspectJAutoProxyCreator 实现的initBeanFactory() 方法

@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    super.initBeanFactory(beanFactory);
    if (this.aspectJAdvisorFactory == null) {
        this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
    }

    // BeanFactoryAspectJAdvisorsBuilderAdapter 的功能是什么?
    this.aspectJAdvisorsBuilder =
            new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}

这里不对代码进行详细的解读,仅仅展示一下执行顺序、调用层级,详细的代码实现自己去看Spring 的源码即可

阅读AnnotationConfigApplicationContext.refresh() 方法,弄清楚Spring 初始化时对于PostProcessor 的创建、Bean 的创建、Aware 实现类的调用时机、Bean 初始化前后调用PostProcessor 实现类的时机等等这些关键逻辑,对于理解Spring 框架是极其重要的!!!!!

AnnotationAwareAspectJAutoProxyCreator的执行时机

AnnotationAwareAspectJAutoProxyCreator 作为后置处理器先注入到IoC 容器中,等到其他的Bean 创建的时候,AnnotationAwareAspectJAutoProxyCreator 会拦截Bean 的初始化过程,做一些定制化处理

主要就是看AnnotationAwareAspectJAutoProxyCreator 的父类AbstractAutoProxyCreator 实现的postProcessBeforeInstantiation()、postProcessAfterInitialization() 做了什么

@Override
public Object postProcessBeforeInstantiation(Class<> beanClass, String beanName) throws BeansException {
    Object cacheKey = getCacheKey(beanClass, beanName);

    if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
        if (this.advisedBeans.containsKey(cacheKey)) {
            return null;
        }
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }

    // Create proxy here if we have a custom TargetSource.
    // Suppresses unnecessary default instantiation of the target bean:
    // The TargetSource will handle target instances in a custom fashion.
    if (beanName != null) {
        TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
        if (targetSource != null) {
            this.targetSourcedBeans.add(beanName);
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
            Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }
    }

    return null;
}


/**
 * Create a proxy with the configured interceptors if the bean is
 * identified as one to proxy by the subclass.
 * @see #getAdvicesAndAdvisorsForBean
 */
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

AnnotationAwareAspectJAutoProxyCreator 实现了SmartInstantiationAwareBeanPostProcessor,而SmartInstantiationAwareBeanPostProcessor 继承自InstantiationAwareBeanPostProcessor

BeanPostProcessor 是在Bean 对象创建完成后初始化前后调用的

而InstantiationAwareBeanPostProcessor 会在任何Bean 创建之前,调用postProcessBeforeInstantiation() 方法。因为是AOP 相关,所以我们只需要关心切面类Bean 和被切面的类Bean 在创建之前,被postProcessBeforeInstantiation() 做了什么

@Override
public Object postProcessBeforeInstantiation(Class<> beanClass, String beanName) throws BeansException {
    Object cacheKey = getCacheKey(beanClass, beanName);

    if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
        /**
         * advisedBeans 保存了需要增强的Bean(也就是想要被切的类,比如之前文章中的MathTool)
         * 每一个创建的Bean 都在这里判断是否是需要增强的Bean
         */
        if (this.advisedBeans.containsKey(cacheKey)) {
            return null;
        }

        /**
         * isInfrastructureClass() 判断当前类是否实现了Advice、Pointcut、Advisor、AopInfrastructureBean 这几个接口中的一个
         *     或者是否是切面:有没有@Aspect 注解
         *     详细看AnnotationAwareAspectJAutoProxyCreator 重写的isInfrastructureClass() 方法
         *     比如之前的例子中
         *     被切的类MathTool 就不满足这个条件
         * shouldSkip() 是否需要跳过?
         */
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }

    // Create proxy here if we have a custom TargetSource.
    // Suppresses unnecessary default instantiation of the target bean:
    // The TargetSource will handle target instances in a custom fashion.
    if (beanName != null) {
        TargetSource targetSource = getCustomTargetSource(beanClass, beanName);

        /**
         * 在之前文章的例子中,走到这一步对于MathTool 这个被切类,在这一步为false,不会执行下面的方法
         */
        if (targetSource != null) {
            this.targetSourcedBeans.add(beanName);
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
            Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }
    }

    /**
     * 在这个方法中针对Bean 在构造之前做一些定制处理
     * 在这个方法return 之后,就开始执行Bean 的构造方法了!
     */
    return null;
}

执行完上面这个方法之后,继续执行Bean 的构造方法,执行完Bean 的构造方法之后,接下来执行postProcessAfterInitialization() 方法

/**
 * Create a proxy with the configured interceptors if the bean is
 * identified as one to proxy by the subclass.
 * @see #getAdvicesAndAdvisorsForBean
 */
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    /**
     * 对于之前例子中的MathTool,构造之后,对应的bean 一定不是null
     */
    if (bean != null) {
        /**
         * 获取Bean
         */
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            /**
             * 如果需要的话,进行包装!!
             * 获取当前Bean 的所有增强器(通知方法)
             *    找到候选的所有增强器(找那些通知方法是需要切入当前bean 方法的
             *    获取到能在bean 使用的增强器
             *    给增强器排序
             * 保存当前bean 到advisedBeans 中,表示当前bean 被增强处理了
             * 创建代理对象
             *    JDK动态代理?
             *    Cglib动态代理?
             * 返回这个Bean 被增强了之后的代理对象
             * 以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程
             */
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

不过多赘述,更多的实现细节,自己去看这个方法背后的源码,以及翻阅相关的资料!后续我可能会针对一些细节再梳理一些文章!

最后,推荐阅读




如果本篇文章对您有所帮助,您可以通过微信(左)或支付宝(右)对作者进行打赏!


上一篇     下一篇