结合Spring中AOP源码浅析① Spring中AOP源码浅析② 这两篇文章我们知道AOP的实现其实是通过引入AnnotationAwareAspectJAutoProxyCreator这个类(注解感知AspectJ自动代理创建器 BeanName:org.springframework.aop.config.internalAutoProxyCreator)去实现的。实际他的底层也是一个InstantiationAwareBeanPostProcessor后置处理器。结合两篇文章,简单画一下它的实现过程。
那么就来分析一下InstantiationAwareBeanPostProcessor 这个后置处理器的前置方法和后置方法分别做了哪些事情。
前置方法在resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd);这里执行,查看源码
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
//确保此时已经解析了Bean
//非合成Bean并且是InstantiationAwareBeanPostProcessors类型的后置处理器
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
//目标Bean的class
Class> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
//执行后置处理器的前置方法
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
我们只需要关注bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);这个方法
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class> beanClass, String beanName) {
//遍历所有后置处理器
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//只拿到InstantiationAwareBeanPostProcessor类型的后置处理器
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//执行前置方法
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
继续从Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);这里进去
这里InstantiationAwareBeanPostProcessor 这个处理器有多个实现类,我们只关注AOP相关的AbstractAutoProxyCreator
因为从Spring中AOP源码浅析①这篇文章中有分析得到 AnnotationAwareAspectJAutoProxyCreator继承自AbstractAutoProxyCreator
继续跟进代码
@Override
public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
//判断增强Bean是否包含当前key,业务Bean肯定不在这里
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
//判断是否为基础组件(通知类切面类等)、判断是否应该跳过
//shouldSkip:找到所有增强器Advisors(即通知方法),第一次会解析切面类并创建增强器
//对于业务Bean 这里返回false
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.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
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;
}
targetSource是一个接口,对于业务Bean来说,如果实现这个接口,则会执行下面的业务创建代理对象,对于普通业务Bean 这一步返回的是空,暂时不关注这一块。
这一步就已经完成了前置处理,主要就在shouldSkip()这个方法里面,对切面类进行解析并创建了增强器Advisors,赋值给了全局变量。
@Override
protected boolean shouldSkip(Class> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names考虑优化 通过 缓存缓存切面名字
// findCandidateAdvisors这一步就是查找所有增强器
List candidateAdvisors = findCandidateAdvisors();
//遍历增强器 查看切面名字是否和传入的Bean相同
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
//父类没有任何操作 直接返回False
return super.shouldSkip(beanClass, beanName);
}
findCandidateAdvisors() 需要在深入看一下具体是如何拿到增强器的。他这里调用了父类的查找方法。
@Override
protected List findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
//调用父类 第一次没有获取到
List advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
//通过 aspectJAdvisorsBuilder 去创建
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
第一次获取不到的,然后通过this.aspectJAdvisorsBuilder.buildAspectJAdvisors()去构建,进去看一下
/**
* Look for AspectJ-annotated aspect beans in the current bean factory,
* and return to a list of Spring AOP Advisors representing them.
* Creates a Spring Advisor for each AspectJ advice method.
* @return the list of {@link org.springframework.aop.Advisor} beans
* @see #isEligibleBean
*/
public List buildAspectJAdvisors() {
List aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
.......
内容很多,我们就只关注重点,重点就是他返回的是List
看一下注释,翻译下:在当前的bean工厂中查找带有AspectJ注释的切面bean(可能不止一个),然后返回Advisor列表代表他们。 为每个AspectJ通知方法创建一个Spring Advisor。
结合debug,这里对我们的切面类进行了解析,并把每个方法封装成了一个Advisor。结合我们的切面类看一下。
//日志切面类
@Aspect
public class LogAspects {
//切点
@Pointcut("execution(public void com.csdn.asong.aop.FunAspects.*(..))")
public void pointCut(){};
//前置 @before代表在目标方法执行前切入, 并指定在哪个方法前切入
@Before("pointCut()")
public void logStart(){
System.out.println("logStart 业务准备执行....");
}
//后置
@After("pointCut()")
public void logEnd(){
System.out.println("logEnd 业务执行结束......");
}
//返回
@AfterReturning("pointCut()")
public void logReturn(){
System.out.println("logReturn 正常返回......");
}
//异常
@AfterThrowing("pointCut()")
public void logException(){
System.out.println("logException 运行异常......");
}
//环绕
@Around("pointCut()")
public Object Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
System.out.println("@Around:执行目标方法之前...");
//执行目标业务方法
Object obj = proceedingJoinPoint.proceed();
System.out.println("@Around:执行目标方法之后...");
return obj;
}
}
所以在List
至此,对于需要增强的业务Bean来说,我们的前置方法就已经完成了他的功能。
所以前置方法完成的任务是什么?对于业务Bean来说,前置方法这一步返回的是空的,但是它完成了解析切面类,拿到了增强器。上一篇文章提到后置处理的方法执完毕后才拿到了真正的代理业务Bean对象,所以增强代码的织入,代理对象的生成由后置处理方法postProcessAfterInstantiation()去完成。
继续 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); 从这里点进去看,找到 InstantiationAwareBeanPostProcessor 处理器执行的后置方法
//遍历所有后置处理器执行相应的后置方法
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
这里是遍历所有+执行所有,我们重点关注的是AnnotationAwareAspectJAutoProxyCreator这个处理器,可以加个断点进去看看执行过程
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
//进入到了这里:包装Bean如果有必要的话
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
从这里wrapIfNecessary(bean, beanName, cacheKey);再进去,这里我们就找到了相应生成代理对象的代码
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//做一些判断,这些可以跳过不看
if (StringUtils.hasLength(beanName) && 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. 创建代理如果我们有通知
// 这里是生成代理对象的过程
//specificInterceptors 特殊拦截器:实际是所有的Advices和Advisors
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[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);这一步是获取所有的特殊拦截器,实际是Advisor增强器,并对其进行排序,因为我们的增强器对应的就是相应切面类里面的通知方法,每个方法都有相应的拦截顺序。
createProxy() 这一步是创建代理,从这一步进去,发现我们的代理对象是通过ProxyFactory 代理工厂生成的。代理工厂就是负责把所有的增强器通过动态代理的方式织入到业务Bean的方法前后。
protected Object createProxy(Class> beanClass, @Nullable String beanName,
@Nullable 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.getProxy(getProxyClassLoader());
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
从这里再进去 是 CglibAopProxy ,因为我们业务Bean 没有响应的接口,所以使用了Cglib创建动态代理的方式。
因为从实现类我们可以看到两个,分别是JDK动态代理和Cglib动态代理
从createAopProxy()的内部实现也可以清楚地看到具体的选择方法:
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
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.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
至此我们就分析完了后置处理器 生成代理对象的过程。至于这两种代理方式以后有空再细细分析。