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 留给我们扩展的接口,那么他是如何定义的呢?我们看看该接口:

public interface BeanPostProcessor {
 Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
 Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

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

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

@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。

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,我们看看该方法实现(该方法对于我们来说已经到终点了),

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 接口来实现的。

猜你喜欢

转载自blog.csdn.net/ghostxbh/article/details/81288365