通过上节我们了解了AnnotationAwareAspectJAutoProxyCreator的其中之一的作用,是作为一个后置处理器在我们创建单实例bean之前拦截尝试着先去创建代理对象,如果是找到了直接返回,当然它作为此类型的【InstantiationAwareBeanPostProcessor】的后置处理器跟我们之前的BeanPostProcessor【后置处理器】是有区别的:
区别
两者最大的区别在于创建bean的执行的时机不同
- BeanPostProcessor:是在我们初始化bean的前后进行相关的操作
- InstantiationAwareBeanPostProcessor:是在我们bean的创建之前进行拦截,然后自己尝试着去创建代理对象,如果存在直接使用此代理对象
所以说,spring中的每一种类型的BeanPostProcessor都有自己的执行时机,这也是对于我们是一个难点,接着我们来说AnnotationAwareAspectJAutoProxyCreator的另外一个作用,首先我们再来复习一下它的类图:
通过它的继承和实现关系,我们还会发现AnnotationAwareAspectJAutoProxyCreator的父类AbstractAutoProxyCreator实现了BeanFactoryAware此接口,那么必然会实现该接口的#setBeanFactory(...)方法
- 在我们的顶级父类AbstractAutoProxyCreator中有这样的一段代码:
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
- 同样不难猜测在它的子类AbstractAdvisorAutoProxyCreator中:
@Override
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
throw new IllegalArgumentException(
"AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
}
initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}
发现子类重写了setBeanFactory(....)方法,说了这么多,我们其主要关注的核心还需要放在顶级分类AbstractAutoProxyCreator中来完成接下来的分析,现在我们要把关注的核心点来放在我们自己编写的业务类和日志切面类的创建
AbstractAutoProxyCreator
在这个类中,它既扮演了postProcessor的角色也扮演了BeanFactoryAware的角色,至于BeanFactoryAware角色来讲我们已经知道它重写了setBeanFactory(...)方法,不必多说,我们在AbstractAutoProxyCreator类中会发现#postProcessBeforeInstantiation(...)和#postProcessAfterInstantiation(...)这两个方法值得我们注意下,我们给他打上断点,首先分析的入口还是我们的测试类:
//Aop测试
@Test
public void testAop(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAop.class);
MathCalculator calculator = applicationContext.getBean(MathCalculator.class);
calculator.div(10,5);
applicationContext.close();
}
跟踪代码我们来到AbstractApplicatContext#refresh()方法,我们一步一步Dbug当来到this.registerBeanPostProcessors(beanFactory)此处是,断点进入我们的AbstractAutoProxyCreator#setBeanFactory(...)方法,直接跳过来到refresh()方法,接着当断点来到this.finishBeanFactoryInitialization(beanFactory)时跳到AbstractAutoProxyCreator#postProcessBeforeInstantiation(....)方法上,那么我们在此时进行分析,当然这里只关心我们自己写的bean的创建具体如下图:
当我们执行完postProcessBeforeInstantiation方法之后会执行postProcessAfterInstantiation方法,两个方法交替执行,多提了一点,回归正题:
- 首先获取当前的bean的名字
Object cacheKey = getCacheKey(beanClass, beanName);
- 通过如下的方式来判断当前bean是否在advisedBeans中存在
private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
其中advisedBeans 保存了所有需要增强的bean,因为此刻我们的需要增强的业务类添加进此缓存中,所以直接跳过此判断来到:
- 通过如下的判断当前bean是否是一个基础类型的bean
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
通过方法#isInfrastructureClass(beanClass)来判断是否是一个基础类型的,那什么是基础类型的bean,跟踪代码来到:
protected boolean isInfrastructureClass(Class<?> beanClass) {
return super.isInfrastructureClass(beanClass) || this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass);
}
这里我们看到的是调用了父类的super.isInfrastructureClass(beanClass)继续跟踪代码来到:
protected boolean isInfrastructureClass(Class<?> beanClass) {
boolean retVal = Advice.class.isAssignableFrom(beanClass) || Pointcut.class.isAssignableFrom(beanClass) || Advisor.class.isAssignableFrom(beanClass) || AopInfrastructureBean.class.isAssignableFrom(beanClass);
if (retVal && this.logger.isTraceEnabled()) {
this.logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
}
return retVal;
}
这里就明确了,原来基础类型是Advice、Pointcut、Advisor、AopInfrastructureBean这些类型,我们的逻辑类肯定不是这些基础类型,直接放行来到上层,其中我们注意一点:this.aspectJAdvisorFactory.isAspect(beanClass)是这个类型的,继续跟踪代码来到:
public boolean isAspect(Class<?> clazz) {
return this.hasAspectAnnotation(clazz) && !this.compiledByAjc(clazz);
}
接着继续跟踪代码来到:
private boolean hasAspectAnnotation(Class<?> clazz) {
return AnnotationUtils.findAnnotation(clazz, Aspect.class) != null;
}
从这里看到,我们的基础类型还包括注解@Aspect,接着来到我们的方法#postProcessBeforeInstantiation()开始位置
同时通过this.shouldSkip(beanClass, beanName)来判断是否需要跳过
通过下面代码来判断是否需要在此处创建代理
TargetSource targetSource = this.getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
在这里创建代理对象的前提时我们已经自定义代理的目标对象,很显然我们是没有的,直接跳过来到#postProcessAfterInitialization(....)方法:
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
其中方法this.wrapIfNecessary(bean, beanName, cacheKey)需要我们注意下,意思是如果需要包装的情况下会调用此方法,我们继续跟踪代码:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
简单的分析下上述代码的过程:
- 通过!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)来判断当前bean是否是基础类型的和是否需要跳过
- 通过如下代码来获取当前bean的所有增强器(也就是通知方法)specificInterceptors
getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource)
跟踪代码来到此方法:
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = this.findEligibleAdvisors(beanClass, beanName);
return advisors.isEmpty() ? DO_NOT_PROXY : advisors.toArray();
}
发现通过继续调用内部的方法#this.findEligibleAdvisors(beanClass, beanName);其中参数为上图中红色框内的,继续跟踪代码来到:
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
this.extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
-
首先一进方法将获取到的后补增强器存放咋list中【candidateAdvisors 】
接着是通过如下的代码是获取能作用于我们当前bean的增强器
List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
我们来看看#findAdvisorsThatCanApply(...)是如何查找的过程
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
List var4;
try {
var4 = AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
} finally {
ProxyCreationContext.setCurrentProxiedBeanName((String)null);
}
return var4;
}
首先一进方法将当前 要增强的bean进行了设置
接着通过Aop的工具去查找,最后进行返回
接着通过如下方法对我们的增强器进行排序操作
this.sortAdvisors(eligibleAdvisors);
下图所示的最终排序之后的增强器
其实就是我们自己编写的切面那些方法,继续跟踪代码:
- 将当前需要增强的bean添加到advisedBeans 中,通过下面代码:
this.advisedBeans.put(cacheKey, Boolean.TRUE);
- 如果当前bean需要增强的话,就为它进行代理对象的创建
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
继续跟踪代码来到AbstractAutoProxyCreator类中的#createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource)方法,我们来看看具体代码创建逻辑过程:
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (this.shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
} else {
this.evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
图中是上述的方法中用到的参数类型,需要我们来注意的一点是 this.evaluateProxyInterfaces(beanClass, proxyFactory)此方法,此方法主要的目的是将当前bean的类型设置为一个ProxyFactory
- 通过如下代码来获取当前bean所有的通知方法(增强器)
Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
- 接着是保存到proxyFactory中
proxyFactory.addAdvisors(advisors);
- 接着通过如下的代码进行代理对象的真正创建过程:
proxyFactory.getProxy(this.getProxyClassLoader());
跟踪代码来到:
public Object getProxy(@Nullable ClassLoader classLoader) {
return this.createAopProxy().getProxy(classLoader);
}
继续看我们的createAopProxy()方法
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
return new JdkDynamicAopProxy(config);
} else {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
} else {
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
}
}
}
通过上面的代码spring自动帮我们创建了ObjenesisCglibAopProxy 类型的CGLIB代理,最后一路返回来到我们AbstractAutoProxyCreator类中的#wrapIfNecessary()方法
- 通过如下操作将当前要增强的组件代理对象的class类型返回给容器中
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
这样做的目的是我们下节要说的,通过创建的代理对象来执行我们的目标方法,那么关于AOP代理对象的创建分析就到这了....