前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深入理解Spring-之-源码剖析AOP(注解方式二)

深入理解Spring-之-源码剖析AOP(注解方式二)

作者头像
用户5224393
发布2019-08-13 15:02:51
3530
发布2019-08-13 15:02:51
举报
文章被收录于专栏:Java研发军团Java研发军团

接着深入理解Spring-之-源码剖析AOP(注解方式一)的章节继续

3. AnnotationAwareAspectJAutoProxyCreator 类

这个类的名字很长,为什么要说这个类呢?还记得我们刚开始说的 BeanPostProcessor 扩展接口吗?

我们说该接口是spring 留给开发人员自定义增强bean的接口。而该类则实现了该接口,看名字也知道,该类是根据注解自动创建代理的创建者类。我们看看他的类图:

可以看到,最底层的该类实现了 BeanPostProcessor 接口,可以在每个bena生成前后做操作。

该类由 Rod Johnson 编写,注释上是这么说的:任何AspectJ注释的类都将自动被识别,它们也会被识别。和我们预想的一致。

我们知道了 AnnotationAwareAspectJAutoProxyCreator 是根据注解自动创建代理,而该类也算是 ProxyBean 的代理,那么,和它一样继承抽象父类的其他几个类的作用是什么呢?

来都来了,就看看吧!我们看看类图:

可以看到该类由4个实现:他们实现了不同的创建代理的方式:

1.匹配Bean的名称自动创建匹配到的Bean的代理,实现类BeanNameAutoProxyCreator

2.根据Bean中的AspectJ注解自动创建代理,实现类 AnnotationAwareAspectJAutoProxyCreator,也就是我们今天说的注解类。

3.根据Advisor的匹配机制自动创建代理,会对容器中所有的Advisor进行扫描,自动将这些切面应用到匹配的Bean中,实现类DefaultAdvisorAutoProxyCreator

4.InfrastructureAdvisorAutoProxyCreator,该类只在 AopConfigUtils 中的静态块用到,该类的注释:自动代理创建者只考虑基础设施顾问bean,忽略任何应用程序定义的顾问。意思应该是只是Sprnig的基础代理,开发者的应用会忽略。有知道的同学可以告诉我。

加上我们的ProxyFactoryBean,一共5种实现方法。从这里可以看出Spring 对于扩展的软件设计是多么优秀。

那么我们就来看看 AnnotationAwareAspectJAutoProxyCreator 是如何创建代理的。我们说 BeanPostProcessor 是Spring 留给我们扩展的接口,那么他是如何定义的呢?我们看看该接口:

代码语言:javascript
复制
public interface BeanPostProcessor {
 Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
 Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

该接口定义了两个方法,一个是在bean初始化之前执行,一个是在bean初始化之后执行。也就是说,开发者可以在这两个方法中做一些有趣的事情。

我们看看 AnnotationAwareAspectJAutoProxyCreator 是如何实现该方法的。实际上 AnnotationAwareAspectJAutoProxyCreator 的抽象父类已经实现了该方法,我们看看是如何实现的:

代码语言:javascript
复制
@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;
 }

before 方法直接返回了bean,并没有做什么增强操作,重点在after方法,我们可以看该方法的注释:如果bean是由子类标识的,那么就创建一个配置的拦截器的代理。

Spring 就是在这里创建了代理,我们进入关键方法 wrapIfNecessary 看看。该方法用来包装给定的Bean。

代码语言:javascript
复制
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
   if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
     return bean;
   }
   if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
     return bean;
   }
   if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
     this.advisedBeans.put(cacheKey, Boolean.FALSE);
     return bean;
   }

   // Create proxy if we have advice.
   Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
   if (specificInterceptors != DO_NOT_PROXY) {
     this.advisedBeans.put(cacheKey, Boolean.TRUE);
     Object proxy = createProxy(
         bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
     this.proxyTypes.put(cacheKey, proxy.getClass());
     return proxy;
   }

   this.advisedBeans.put(cacheKey, Boolean.FALSE);
   return bean;
 }

我们已将可以看到一个关键一行代码:Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)),创建一个代理,该方法携带了bean的Class对象,benaName, 通知器数组,还有一个包装过的单例Bean,我们看看该方法实现(该方法对于我们来说已经到终点了),

代码语言:javascript
复制
protected Object createProxy(
     Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

   if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
     AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
   }

   ProxyFactory proxyFactory = new ProxyFactory();
   proxyFactory.copyFrom(this);

   if (!proxyFactory.isProxyTargetClass()) {
     if (shouldProxyTargetClass(beanClass, beanName)) {
       proxyFactory.setProxyTargetClass(true);
     }
     else {
       evaluateProxyInterfaces(beanClass, proxyFactory);
     }
   }

   Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
   proxyFactory.addAdvisors(advisors);
   proxyFactory.setTargetSource(targetSource);
   customizeProxyFactory(proxyFactory);

   proxyFactory.setFrozen(this.freezeProxy);
   if (advisorsPreFiltered()) {
     proxyFactory.setPreFiltered(true);
   }

   return proxyFactory.getProxy(getProxyClassLoader());
 }

我们能够看到其中有一行让我们激动的代码,就是 ProxyFactory proxyFactory = new ProxyFactory(),创建了一个ProxyFactory 对象。

我们刚刚说过,该对象和ProxyFactoryBean一样,继承了 ProxyCreatorSupport, 因此也就和 ProxyFactoryBean 一样拥有了 getProxy 方法。

到这里,我们的一切都豁然开朗。当然上面几行代码是设置了通知器链。我们先按下不表。

ProxyFactoryBean 扩展了 FactoryBean 接口, AnnotationAwareAspectJAutoProxyCreator 扩展了 BenaPostProcessor 了接口,其目的都是在Bean生成的时候做增强操作,Spring 通过这两种方式,完成了两种不同的代理生成方式,但最终都是继承了 ProxyCreatorSupport 类,该类才是生成代理的核心类。

我们可以看看XML 配置方式和 注解方式的方法堆栈调用图,从中我们可以看出一些端倪:

XML 配置方式堆栈图

注解配置方法堆栈图

我们可以看到两者在AbstractBeanFactory 的 doGetBean 方法开始分道扬镳,走向了不同的逻辑,那么我们看看到底哪里不同,直接看代码:我们看XML配置堆栈,在258行:

从这里进入,该方法做了些什么呢?为什么让他们走向不同的路线?我们看看该方法:

该方法有个重要的判断:是否是 FactoryBean 的子类型,很明显,我们的XML配置的ProxyFacoroyBean 返回 false,而注解方式的Bean则返回 false,ProxyFacoroyBean 会一直向下走,直到创建代理,而注解方式则会直接返回。走到302行:

注解方式会执行 getSingleton 方法,最后触发 createBean 回调方法,完成创建代理的过程。

到此为止,现在我们知道了到 XML 配置方式的 AOP 和注解的方式AOP 的生成区别。我们可以开始总结了。

4. 总结

首先,通过分析源码我们知道注解方式和 XML 配置方式的底层实现都是一样的,都是通过继承 ProxyCreatorSupport 来实现的,不同的通过扩展不同的 Spring 提供的接口,XML 扩展的是FactoryBean 接口, 而注解方式扩展的是 BenaPostProcessor 接口,通过Spring 的扩展接口,能够对特定的Bean进行增强。

而 AOP 正式通过这种方式实现的。这也提醒了我们,我们也可以通过扩展 Spring 的某些接口来增强我们需要的 Bean 的某些功能。

当然,篇幅有限,我们这篇文章只是了解了XML 配置方式和注解方式创建代理的区别,关于如何 @Aspect 和 @Around 的底层实现,还有通知器的底层实现,我们还没有分析,但我们隐隐的感觉到,其实万变不离其宗,底层的也是通过扩展 advice 和 pointcut 接口来实现的。

我们将会在后面的文章继续分析 AOP 是如何编织通知的。

END

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-07-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java研发军团 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • XML 配置方式堆栈图
  • 注解配置方法堆栈图
相关产品与服务
云顾问
云顾问(Tencent Cloud Smart Advisor)是一款提供可视化云架构IDE和多个ITOM领域垂直应用的云上治理平台,以“一个平台,多个应用”为产品理念,依托腾讯云海量运维专家经验,助您打造卓越架构,实现便捷、灵活的一站式云上治理。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档