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