Spring源码深度解析(郝佳)-学习-源码解析-aop代理创建(五)

前面几篇博客中己经对切面表达式的解析,匹配己经做过详细的介绍了,今天我们来研究一下,当表达式和目标类方法匹配成功以后,又是如何创建代理的呢?今天,我们将围绕这个话题,再次来研究。先上示例。

AspectJTest

@Aspect
@Configuration
public class AspectJTest {
    @Before("execution(* com.spring_101_200.test_111_120.test_117_excution.excution1.*.*(..))")
    public void beforeTest() {
        System.out.println("beforeTest");
    }
}

今天我们主要分析Spring 是如何解析 execution(* com.spring_101_200.test_111_120.test_117_excution.excution1..(…)) 表达式。

MyService.java

@Service
public class MyService {
    public void service() {
        System.out.println("serivce");
    }
}

spring_117_excution1.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">


    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    <context:component-scan base-package="com.spring_101_200.test_111_120.test_117_excution.excution1"></context:component-scan>


</beans>

测试:

public static void main(String[] args) {
    ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring_101_200/config_111_120/spring117_excution/spring_117_excution1.xml");
    MyService myService = ac.getBean(MyService.class);
    myService.service();
}

结果输出:

在这里插入图片描述

在AnnotationAwareAspectJAutoProxyCreator的父类 AbstractAutoProxyCreator 的 postProcessAfterInitlization 中代码如下:

AbstractAutoProxyCreator.java

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
	if (bean != null) {
		//根据给定的 bean 的 class 和 name 构建出一个 key,格式:beanClassName_beanName
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		//从缓存中获取代理引用
		if (!this.earlyProxyReferences.contains(cacheKey)) {
			//如果它适合代理,则需要封装指定的bean
			return wrapIfNecessary(bean, beanName, cacheKey);
		}
	}
	return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	//如果己经处理过
	if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
		return bean;
	}
	//如果advisedBeans己经包含,并对应的值是 false,无须增强
	if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
		return bean;
	}
	//如果类是Advice或AopInfrastructureBean的子类 ,或者可以跳过aop,直接返回 bean,不创建代理
	if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

	//如果存在增强方法则创建代理
	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;
}

        函数中我们己经看到了代理创建的雏形,当然,真正开始之前还需要经过一些判断,比如是否己经处理或者是否需要跳过的 bean,而真正创建代理的代码是从 getAdvicesAndAdvisorsForBean 开始的。
        创建代理主要包含以下的两个步骤

  • 获取增强方法或者增强器。
  • 根据获取的增强进行代理。
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
	List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
	//如果通知器为空,直接返回不需要代理
	if (advisors.isEmpty()) {
		return DO_NOT_PROXY;
	}
	return advisors.toArray();
}
protected List findEligibleAdvisors(Class<?> beanClass, String beanName) {
	List candidateAdvisors = findCandidateAdvisors();
	List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
	extendAdvisors(eligibleAdvisors);
	if (!eligibleAdvisors.isEmpty()) {
		//对当前类对应的 advisor进行排序,这一步也很关键,比如类上配置了@Order注解,就在这里控制
		eligibleAdvisors = sortAdvisors(eligibleAdvisors);
	}
	return eligibleAdvisors;
}
获取增强器

        对于指定的 bean 的增强方法的获取一定包含两个步骤,获取所有的增强以及寻找所有的增强适用于 bean的增强并应用,那么 findCanddidateAdvisors 与findAdvisorsThatCanApply 便是做了这两件事情,当然如果无法找到对应的增强器便返回 DO_NOT_PROXY,其中DO_NOT_PROXY=null。

        在之前的博客中讲解了自定义配置完成对AnnotationAwareAspectJAutoProxyCreator类型的自动注册,那么这个类到底是来完成什么样的工作的呢?首先我们来看看AnnotationAwareAspectJAutoProxyCreator类层次结构
在这里插入图片描述
在类的层级中,我们看到了 AnnotationAwareAspectJAutoProxyCreator 实现了 BeanPostProcessor接口,而实现了 BeanPostProcessor后,当 Spring 加载这个 Bean 时,会在实例化前调用其 postProcessAfterInitlization 方法,而我们对于 AOP 逻辑的分析也由此开始。

AnnotationAwareAspectJAutoProxyCreator.java
protected List<Advisor> findCandidateAdvisors() {
	//当使用注解方式配置 AOP的时候并不是丢弃了对 XML配置的支持,在这里调用父类方法加载配置文件中的 AOP 声明
	List<Advisor> advisors = super.findCandidateAdvisors();
	advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
	return advisors;
}

        AnnotationAwareAspectJAutoProxyCreator间接继承了 AbstractAdvisorAutoProxyCreator,在实现获取增强的方法中除了保留父类的获取配置文件中定义的增强外,同时添加了获取 Bean 的注解增强的功能,那么其实现在正是由 this.aspectJAdvisorsBuilder.buildAspectJAdvisors()来实现的。

AbstractAdvisorAutoProxyCreator.java
protected List<Advisor> findCandidateAdvisors() {
	return this.advisorRetrievalHelper.findAdvisorBeans();
}
BeanFactoryAdvisorRetrievalHelper.java
public List<Advisor> findAdvisorBeans() {
	//通知器名称列表
	String[] advisorNames = null;
	synchronized (this) {
		advisorNames = this.cachedAdvisorBeanNames;
		if (advisorNames == null) {
			//不要在这里初始化FactoryBeans:我们需要保留所有未初始化的常规bean,以使自动代理创建者对其应用!
			advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
					this.beanFactory, Advisor.class, true, false);
			this.cachedAdvisorBeanNames = advisorNames;
		}
	}
	if (advisorNames.length == 0) {
		return new LinkedList<Advisor>();
	}
	List<Advisor> advisors = new LinkedList<Advisor>();
	for (String name : advisorNames) {
		if (isEligibleBean(name)) {
			if (this.beanFactory.isCurrentlyInCreation(name)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Skipping currently created advisor '" + name + "'");
				}
			}
			else {
				try {
					//将当前advisorNames 对应的bean 加入到 advisors 中
					advisors.add(this.beanFactory.getBean(name, Advisor.class));
				}
				catch (BeanCreationException ex) {
					Throwable rootCause = ex.getMostSpecificCause();
					if (rootCause instanceof BeanCurrentlyInCreationException) {
						BeanCreationException bce = (BeanCreationException) rootCause;
						if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {
							if (logger.isDebugEnabled()) {
								logger.debug("Skipping advisor '" + name +
										"' with dependency on currently created bean: " + ex.getMessage());
							}
							continue;
						}
					}
					throw ex;
				}
			}
		}
	}
	return advisors;
}

        在真正的研究代码之前读者可以尝试着自己去想象一下解析思路,看看自己的实现与 Spring 是否在差别呢?或者我们改以往的方式,先来了解函数提供的大概功能框架,读者可以在头脑中尝试实现这些功能点,看看是否有思路。

  1. 获取所有的 beanName,这一步骤中所有的 beanFactory 注册的 bean 都会被提取出来。
  2. 遍历所有的 beanName,并找出声明 AspectJ 注解的类,进行进一步的处理。
  3. 对标记为 AspectJ 注解的类进行增强器的提取。
  4. 将提取的结果加入到缓存中。

现在我们来看看函数实现,对 Spring 中所有的类进行分析,提取 advisor 。

BeanFactoryAspectJAdvisorsBuilder.java
public List<Advisor> buildAspectJAdvisors() {
	List<String> aspectNames = null;

	synchronized (this) {
		aspectNames = this.aspectBeanNames;
		if (aspectNames == null) {
			List<Advisor> advisors = new LinkedList<Advisor>();
			aspectNames = new LinkedList<String>();
			//获取当前容器中所有的 bean 名称
			String[] beanNames =
					BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
			//循环所有的 beanName 找出对应的增强方法
			for (String beanName : beanNames) {
				//不合法的 bean则跳过,由子类定义规则,默认返回 true
				if (!isEligibleBean(beanName)) {
					continue;
				}
				//我们必须小心,不要急于实例化bean,因为在这种情况下,它们将被Spring容器缓存,但不会被编织
				//获取对应的 bean类型
				Class<?> beanType = this.beanFactory.getType(beanName);
				if (beanType == null) {
					continue;
				}
				//是否有Aspect注解,有则加入到aspectNames
				if (this.advisorFactory.isAspect(beanType)) {
					aspectNames.add(beanName);
					AspectMetadata amd = new AspectMetadata(beanType, beanName);
					if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
						MetadataAwareAspectInstanceFactory factory =
								new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
						//发现当前类方法中是否配置了Before, Around, After, AfterReturning, 
						//AfterThrowing, Pointcut注解
						List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
						if (this.beanFactory.isSingleton(beanName)) {
							this.advisorsCache.put(beanName, classAdvisors);
						}
						else {
							this.aspectFactoryCache.put(beanName, factory);
						}
						advisors.addAll(classAdvisors);
					}
					else {
						//如果当前 bean 不是单例
						if (this.beanFactory.isSingleton(beanName)) {
							throw new IllegalArgumentException("Bean with name '" + beanName +
									"' is a singleton, but aspect instantiation model is not singleton");
						}
						MetadataAwareAspectInstanceFactory factory =
								new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
						this.aspectFactoryCache.put(beanName, factory);
						advisors.addAll(this.advisorFactory.getAdvisors(factory));
					}
				}
			}
			this.aspectBeanNames = aspectNames;
			return advisors;
		}
	}

	if (aspectNames.isEmpty()) {
		return Collections.emptyList();
	}
	List<Advisor> advisors = new LinkedList<Advisor>();
	//记录到缓存中
	for (String aspectName : aspectNames) {
		//从 advisors 缓存中获取
		List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
		if (cachedAdvisors != null) {
			advisors.addAll(cachedAdvisors);
		}
		else {
			//获取到工厂方法,再从工厂方法中获取 advisors
			MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
			advisors.addAll(this.advisorFactory.getAdvisors(factory));
		}
	}
	return advisors;
}

ReflectiveAspectJAdvisorFactory.java

private static final Comparator<Method> METHOD_COMPARATOR;

static {
	CompoundComparator<Method> comparator = new CompoundComparator<Method>();
	comparator.addComparator(new ConvertingComparator<Method, Annotation>(
			new InstanceComparator<Annotation>(
					Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
			new Converter<Method, Annotation>() {
				@Override
				public Annotation convert(Method method) {
					AspectJAnnotation<?> annotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
					return annotation == null ? null : annotation.getAnnotation();
				}
			}));
	comparator.addComparator(new ConvertingComparator<Method, String>(
			new Converter<Method, String>() {
				@Override
				public String convert(Method method) {
					return method.getName();
				}
			}));
	METHOD_COMPARATOR = comparator;
}

上面配置了的 comparator 主要是对方法进行排序。
1.配置了@Around, … @AfterThrowing注解的方法排在前面。没有配置的排在后面
2.配置了注解的方法,配置@Around注解的方法排在前面,配置了@AfterThrowing方法排在后面,如果配置相同注解,按照方法名排序,也就是 a方法名一定排在 b方法名前面。
3.没有配置注解,按照方法名排序。

@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) {
	//获取标记为 AspectJ的类
	final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass();
	//获取标记为 AspectJ 的 name
	final String aspectName = maaif.getAspectMetadata().getAspectName();
	//验证  
	validate(aspectClass);
	
	//我们需要用装饰器包装MetadataAwareAspectInstanceFactory ,以便仅实例化一次。
	final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
			new LazySingletonAspectInstanceFactoryDecorator(maaif);

	final List<Advisor> advisors = new LinkedList<Advisor>();
	//获取所有的通知器方法,排除配置了@Pointcut 注解的方法
	for (Method method : getAdvisorMethods(aspectClass)) {
		//找到配置了Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class
		//注解的方法,如果 advisor不为空,则加入到集合中
		Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
		if (advisor != null) {
			advisors.add(advisor);
		}
	}

	//如果 advisors 不为空,则判断当前类类型是否是pertarget,perthis,或pertypewithin,如果是,
	//则创建SyntheticInstantiationAdvisor,并加入到通知器最开始
	if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
		//如果寻找的增强器不为空且又配置了增强延迟初始化,那么需要在首位加入同步实例化增强器
		Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
		advisors.add(0, instantiationAdvisor);
	}

	//查找引介属性,如果属性中配置了DeclareParents注解,创建DeclareParentsAdvisor加入到当前通知器中
	for (Field field : aspectClass.getDeclaredFields()) {
		Advisor advisor = getDeclareParentsAdvisor(field);
		if (advisor != null) {
			advisors.add(advisor);
		}
	}

	return advisors;
}
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
	final List<Method> methods = new LinkedList<Method>();
	ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
		@Override
		public void doWith(Method method) throws IllegalArgumentException {
			//获取所有没有配置 Pointcut 注解的方法
			if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
				methods.add(method);
			}
		}
	});
	//将所有的方法排序 ,先按照注解顺序,Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class,
	//如:配置了@Around注解的方法排在最前面,配置了@AfterReturning注解方法排在后面,如果同时配置了@Around注解,则
	//按方法名称排序,a方法名的在前,b 方法名的在后,ab 方法名在前,ac 方法名在后。
	//如果没有配置注解的方法,直接按照方法名排序 
	Collections.sort(methods, METHOD_COMPARATOR);
	return methods;
}

        函数中首先完成了对增强器的获取,包括获取注解以及根据注解生成增强的步骤,然后考虑到在配置可能会将增强配置成延迟初始化,那么需要在首位加入同步实例化增强器以保证增强使用之前的实例化,最后是对 DeclareParents 注解的获取,下面将详细介绍一下每个步骤。

1. 普通增强器的获取

        普通增强器的获取逻辑通过 getAdvisor 方法实现,实现步骤包括对切点的注解的获取以根据注解信息生成增强。

ReflectiveAspectJAdvisorFactory
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif,
        int declarationOrderInAspect, String aspectName) {
	//再次做较验,比如
	//1.当前类父类配置了@Aspect注解,但是又不是抽象类,抛出异常
	//2.当前类没有配置@Aspect 注解
	//3.当前类的类型是percflow或percflowbelow,抛出 Spring 不支持此类 aop
    validate(aif.getAspectMetadata().getAspectClass());
    //获取当前方法的通知器
    AspectJExpressionPointcut ajexp = getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass());
    if (ajexp == null) {
        return null;
    }
    //第一个参数是AspectJAdvisorFactory,也就是 Advisor工厂,根据切点信息生成增强器
    return new InstantiationModelAwarePointcutAdvisorImpl(
            this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName);
}

1.切点信息的获取,所谓获取莫妮卡中信息就是指定注解的表达式信息的获取,如@Before(“test”)

private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
	//获取方法上的注解
    AspectJAnnotation<?> aspectJAnnotation =
            AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    if (aspectJAnnotation == null) {
        return null;
    }
    //使用AspectJExpressionPointcut实例封装获取信息
    AspectJExpressionPointcut ajexp =
            new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
    //提取到@Before("execution(* com.spring_101_200.test_111_120.test_117_excution.excution1.*.*(..))") 
    //中的execution(* com.spring_101_200.test_111_120.test_117_excution.excution1.*.*(..))表达式
    ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
    return ajexp;
}
AbstractAspectJAdvisorFactory.java
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
	//设置敏感的注解类
    Class<?>[] classesToLookFor = new Class<?>[] {
            Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
    for (Class<?> c : classesToLookFor) {
        AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class) c);
        if (foundAnnotation != null) {
            return foundAnnotation;
        }
    }
    return null;
}
//获取指定方法上的注解并使用AspectJAnnotation封装
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
    A result = AnnotationUtils.findAnnotation(method, toLookFor);
    if (result != null) {
        return new AspectJAnnotation<A>(result);
    }
    else {
        return null;
    }
}

AspectJAnnotation.java

//当前方法面配置注解
private final A annotation;
//当前方法的注解类型
private final AspectJAnnotationType annotationType;

private final String pointcutExpression;

private final String argumentNames;

static {
    annotationTypes.put(Pointcut.class,AspectJAnnotationType.AtPointcut);
    annotationTypes.put(After.class,AspectJAnnotationType.AtAfter);
    annotationTypes.put(AfterReturning .class,AspectJAnnotationType.AtAfterReturning);
    annotationTypes.put(AfterThrowing .class,AspectJAnnotationType.AtAfterThrowing);
    annotationTypes.put(Around.class,AspectJAnnotationType.AtAround);
    annotationTypes.put(Before.class,AspectJAnnotationType.AtBefore);
}

public AspectJAnnotation(A annotation) {
    this.annotation = annotation;
    this.annotationType = determineAnnotationType(annotation);
    try {
    	//注解表达式
        this.pointcutExpression = resolveExpression(annotation);
        //注解上配置了argNames的值,如
		//@Pointcut(value = "execution(* com..excution22.*.*(..))&& args(userName,..) " , argNames = "userName"),
		//这样配置的argNames的值userName,在这里通过反射调用注解的方法获取
        this.argumentNames = (String) annotation.getClass().getMethod("argNames").invoke(annotation);
    }
    catch (Exception ex) {
        throw new IllegalArgumentException(annotation + " cannot be an AspectJ annotation", ex);
    }
}

private AspectJAnnotationType determineAnnotationType(A annotation) {
    for (Class<?> type : annotationTypes.keySet()) {
    	//如果当前注解类型是annotation,或者其子类,这里设计的非常巧妙
    	//如果我们自己写了一个注解,继承了@Before.class注解,也是可以实现切面的,方便我们业务扩展
        if (type.isInstance(annotation)) {
            return annotationTypes.get(type);
        }
    }
    throw new IllegalStateException("Unknown annotation type: " + annotation.toString());
}

private String resolveExpression(A annotation) throws Exception {
    String expression = null;
    for (String methodName : new String[] {"value", "pointcut"}) {
        Method method;
        try {
        	//获取注解的value或者pointcut方法
            method = annotation.getClass().getDeclaredMethod(methodName);
        }
        catch (NoSuchMethodException ex) {
            method = null;
        }
        //如果方法不为空,反射获取 value 值或者 pointcut配置的值
        if (method != null) {
            String candidate = (String) method.invoke(annotation);
            if (StringUtils.hasText(candidate)) {
                expression = candidate;
            }
        }
    }
    return expression;
}


2.根据切点信息生成增强,所有的增强器都是由 Advisor的实现类InstantiationModelAwarePointcutAdvisorImpl统一封装的,AspectJAnnotation这个类的构建,主要是将 advisor 的注解,注解类型,表达式,以及配置的argNames值初始化,在InstantiationModelAwarePointcutAdvisorImpl的实例化过程中,根据annotationType类型生成相应的 Advisor,下面我们来跟进InstantiationModelAwarePointcutAdvisorImpl的创建过程。

InstantiationModelAwarePointcutAdvisorImpl.java
public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJExpressionPointcut ajexp,
        MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) {
    this.declaredPointcut = ajexp;
    this.method = method;
    //初始化Advisor 工厂
    this.atAspectJAdvisorFactory = af;
    this.aspectInstanceFactory = aif;
    this.declarationOrder = declarationOrderInAspect;
    this.aspectName = aspectName;

    if (aif.getAspectMetadata().isLazilyInstantiated()) {
    	//如果切入点是延迟初始化
        Pointcut preInstantiationPointcut =
                Pointcuts.union(aif.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
		//使其具有动态性:必须从实例化前状态更改为实例化后状态。 
		//如果不是动态切入点,则可以在第一次评估之后由Spring AOP基础结构对其进行优化。
        this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aif);
        this.lazy = true;
    }
    else {
    	//如果aop为非惰性
        this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
        this.pointcut = declaredPointcut;
        this.lazy = false;
    }
}

        在封装的过程中只是简单的将信息封装在类的实例化中,所有的信息单纯的赋值,在实例化过程中还完成了对于增强器的初始化,因为不同的增强所体现的逻辑是不同的,比如@Before(“test()”)与@After(“test()”)标签的不同就是增强器的增强的位置不同,所以就需要不同的增强器来完成不同的逻辑,而根据注解中的信息初始化对应的增强器就是在instantiateAdvice实现的

private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
    return this.atAspectJAdvisorFactory.getAdvice(
            this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
}
ReflectiveAspectJAdvisorFactory.java
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp,
        MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) {

    Class<?> candidateAspectClass = aif.getAspectMetadata().getAspectClass();
    validate(candidateAspectClass);
	
    AspectJAnnotation<?> aspectJAnnotation =
            AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    if (aspectJAnnotation == null) {
        return null;
    }

   	//是否是@Aspect注解类
    if (!isAspect(candidateAspectClass)) {
        throw new AopConfigException("Advice must be declared inside an aspect type: " +
                "Offending method '" + candidateAdviceMethod + "' in class [" +
                candidateAspectClass.getName() + "]");
    }

    if (logger.isDebugEnabled()) {
        logger.debug("Found AspectJ method: " + candidateAdviceMethod);
    }

    AbstractAspectJAdvice springAdvice;
	//根据不同的注解类型封装不同的增强器
    switch (aspectJAnnotation.getAnnotationType()) {
        case AtBefore://如果方法配置了@Before,则创建AspectJMethodBeforeAdvice通知器
            springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif);
            break;
        case AtAfter: //如果方法配置了@After,则创建AspectJAfterAdvice通知器
            springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif);
            break;
        case AtAfterReturning:
            springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif);
            AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
            if (StringUtils.hasText(afterReturningAnnotation.returning())) {
            	//设置返回值名称
                springAdvice.setReturningName(afterReturningAnnotation.returning());
            }
            break;
        case AtAfterThrowing:
            springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif);
            AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
            if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
            	//设置异常名称
                springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
            }
            break;
        case AtAround:
            springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif);
            break;
        case AtPointcut://如果方法配置了@Pointcut,则不做任何处理
            if (logger.isDebugEnabled()) {
                logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
            }
            return null;
        default:
            throw new UnsupportedOperationException(
                    "Unsupported advice type on method " + candidateAdviceMethod);
    }
	//设置切面名,如:AspectJTest#0
    springAdvice.setAspectName(aspectName);
    //设置当前方法在第几次调用,数值越小,方法调用时间越早
    springAdvice.setDeclarationOrder(declarationOrderInAspect);
    //从注解中获取参数名,从argNames,以逗号隔开
    String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
    if (argNames != null) {
        springAdvice.setArgumentNamesFromStringArray(candidateAdviceMethod);
    }
    //绑定参数名
    springAdvice.calculateArgumentBindings();
    return springAdvice;
}

        从函数中可以看出,Spring 会根据不同的注解生成不同的增强器,例如 AtBefore会对应 AspectJMethodBeforeAdvice,而在 AspectJMethodBeforeAdvice中完成了增强方法的逻辑,我们尝试分析几个常用的增强器的实现。

我们先来看看MethodBeforeAdviceInterceptor类的内部实现

MethodBeforeAdviceInterceptor.java
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
	private MethodBeforeAdvice advice;

	/**
	 * Create a new MethodBeforeAdviceInterceptor for the given advice.
	 * @param advice the MethodBeforeAdvice to wrap
	 */
	public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
		return mi.proceed();
	}

}

其中的属性 MethodBeforeAdvice 代表着前置增强的MethodBeforeAdvice,跟踪 before 方法:

AspectJMethodBeforeAdvice
public void before(Method method, Object[] args, Object target) throws Throwable {
	invokeAdviceMethod(getJoinPointMatch(), null, null)}
}
AbstractAspectJAdvice
protected Object invokeAdviceMethod(JoinPointMatch jpMatch, Object returnValue, Throwable ex) throws Throwable {
	return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
}

protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
	Object[] actualArgs = args;
	if (this.aspectJAdviceMethod.getParameterTypes().length == 0) {
		actualArgs = null;
	}
	try {
		ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
		//激活增强方法
		return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
	}
	catch (IllegalArgumentException ex) {
		throw new AopInvocationException("Mismatch on arguments to advice method [" +
				this.aspectJAdviceMethod + "]; pointcut expression [" +
				this.pointcut.getPointcutExpression() + "]", ex);
	}
	catch (InvocationTargetException ex) {
		throw ex.getTargetException();
	}
}

        invokeAdviceMethodWithGivenArgs方法中的aspectJAdviceMethod正是对于前置增强方法,在这里实现了调用。
        AspectJAfterAdvice
后置增强与前置增强有我没说过不一致的地方,回顾之前讲过的前置增强,大致的结构是在拦截器链中放置了 MethodBeforeAdviceInterceptor,而在 MethodBeforeAdviceInterceptor中又放置了 AspectJMethodBeforeAdvice,并调用了 invoke 时首先串联调用,但是后置增强的时候就不一样了,没有提供中间类,而是直接在拦截器链中使用了中间 AspectJAfterAdvice。

AspectJAfterAdvice.java
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice {

	public AspectJAfterAdvice(
			Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {

		super(aspectJBeforeAdviceMethod, pointcut, aif);
	}

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			return mi.proceed();
		}
		finally {
			//激活增强方法
			invokeAdviceMethod(getJoinPointMatch(), null, null);
		}
	}

	@Override
	public boolean isBeforeAdvice() {
		return false;
	}

	@Override
	public boolean isAfterAdvice() {
		return true;
	}

}

2.增加同步实例化增强器。

        如果寻找的增强器不为空而且又配置了增强延迟初始化,那么就需要在首位加入同步实例化增强器,同步实例化增强器 SyntheticInstantiationAdvisor如下:

SyntheticInstantiationAdvisor
protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor {

	public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) {
		super(aif.getAspectMetadata().getPerClausePointcut(), new MethodBeforeAdvice() {
			@Override
			//目标方法调用前,类似@Before
			public void before(Method method, Object[] args, Object target) {
				//简单初始化 aspectj
				aif.getAspectInstance();
			}
		});
	}
}
3.获取 DeclareParents注解

        DeclareParents 主要用于引介增强的注解形式实现,而其实现方式与普通增强很类似,只不过使用了 DeclareParentsAdvicesor 对功能进行封装。

ReflectiveAspectJAdvisorFactory.java
private Advisor getDeclareParentsAdvisor(Field introductionField) {
	DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
	if (declareParents == null) {
		// Not an introduction field
		return null;
	}

	if (DeclareParents.class == declareParents.defaultImpl()) {
		// This is what comes back if it wasn't set. This seems bizarre...
		// TODO this restriction possibly should be relaxed
		throw new IllegalStateException("defaultImpl must be set on DeclareParents");
	}

	return new DeclareParentsAdvisor(
			introductionField.getType(), declareParents.value(), declareParents.defaultImpl());
}
AbstractAspectJAdvice.java
public synchronized final void calculateArgumentBindings() {
	//方法参数个数
    if (this.argumentsIntrospected || this.adviceInvocationArgumentCount == 0) {
        return;
    }

    int numUnboundArgs = this.adviceInvocationArgumentCount;
    Class<?>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
    //如果第一个参数类型是JoinPoint或ProceedingJoinPoint类型
    if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0])) {
        numUnboundArgs--;
    }
	//如果第一个参数类型是JoinPoint.StaticPart
    else if (maybeBindJoinPointStaticPart(parameterTypes[0])) {
        numUnboundArgs--;
    }
	//如果参数个数还是大于0
    if (numUnboundArgs > 0) {
    	//绑定参数名
        bindArgumentsByName(numUnboundArgs);
    }
    this.argumentsIntrospected = true;
}
private void bindArgumentsByName(int numArgumentsExpectingToBind) {
    if (this.argumentNames == null) {
    	//获取参数名
        this.argumentNames = createParameterNameDiscoverer().getParameterNames(this.aspectJAdviceMethod);
    }
    if (this.argumentNames != null) {
        bindExplicitArguments(numArgumentsExpectingToBind);
    }
    else {
        throw new IllegalStateException("Advice method [" + this.aspectJAdviceMethod.getName() + "] " +
                "requires " + numArgumentsExpectingToBind + " arguments to be bound by name, but " +
                "the argument names were not specified and could not be discovered.");
    }
}
protected ParameterNameDiscoverer createParameterNameDiscoverer() {
	//添加默认的方法参数名发现类,
	//1.StandardReflectionParameterNameDiscoverer 标准反射参数名发现器,利用反射实现
	//2.LocalVariableTableParameterNameDiscoverer 本地变量表参数名发现器,这个主要是利用 ASM 技术,从常量池中读取方法参数名
    DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
    AspectJAdviceParameterNameDiscoverer adviceParameterNameDiscoverer =
            new AspectJAdviceParameterNameDiscoverer(this.pointcut.getExpression());
    adviceParameterNameDiscoverer.setReturningName(this.returningName);
    adviceParameterNameDiscoverer.setThrowingName(this.throwingName);
    adviceParameterNameDiscoverer.setRaiseExceptions(true);
    //3.加入自定义AspectJAdviceParameterNameDiscoverer方法参数名发现器
    discoverer.addDiscoverer(adviceParameterNameDiscoverer);
    return discoverer;
}
public String[] getParameterNames(Method method) {
	//先通过反射找方法参数名,如果找不到,通过 ASM 技术,从字节码常量池中查找方法参数名
	// 从常量池中读取方法参数,在之前的博客中己经详细讲解了字节码结构,Spring ASM 是如何读取 java字节码的
	// 这里就不再赘述了
    for (ParameterNameDiscoverer pnd : this.parameterNameDiscoverers) {
        String[] result = pnd.getParameterNames(method);
        if (result != null) {
            return result;
        }
    }
    return null;
}
private void bindExplicitArguments(int numArgumentsLeftToBind) {
    this.argumentBindings = new HashMap<String, Integer>();
	//参数名个数不等于参数类型个数,抛出异常
    int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterTypes().length;
    if (this.argumentNames.length != numExpectedArgumentNames) {
        throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames
                + " arguments to bind by name in advice, but actually found " +
                this.argumentNames.length + " arguments.");
    }

    //跳过方法参数JoinPoint或ProceedingJoinPoint类型,因为JoinPoint 只能配置在方法的第一个参数    
    int argumentIndexOffset = this.adviceInvocationArgumentCount - numArgumentsLeftToBind;
    for (int i = argumentIndexOffset; i < this.argumentNames.length; i++) {
        this.argumentBindings.put(this.argumentNames[i], i);
    }
    
    if (this.returningName != null) {
    	//如果方法注解配置了returning,但是方法名中没有returningName,直接抛出异常 
        if (!this.argumentBindings.containsKey(this.returningName)) {
            throw new IllegalStateException("Returning argument name '"
                    + this.returningName + "' was not bound in advice arguments");
        }
        else {
            Integer index = this.argumentBindings.get(this.returningName);
            //设置方法的返回值类型
            this.discoveredReturningType = this.aspectJAdviceMethod.getParameterTypes()[index];
            //设置方法的泛型返回值类型
            this.discoveredReturningGenericType = this.aspectJAdviceMethod.getGenericParameterTypes()[index];
        }
    }
    if (this.throwingName != null) {
    	//同理,如果方法注解上配置了 throwing,而方法绑定参数名中没有该值,抛出异常
        if (!this.argumentBindings.containsKey(this.throwingName)) {
            throw new IllegalStateException("Throwing argument name '"
                    + this.throwingName + "' was not bound in advice arguments");
        }
        else {
            Integer index = this.argumentBindings.get(this.throwingName);
            //设置方法异常返回值类型
            this.discoveredThrowingType = this.aspectJAdviceMethod.getParameterTypes()[index];
        }
    }
	
    configurePointcutParameters(argumentIndexOffset);
}


private void configurePointcutParameters(int argumentIndexOffset) {
    int numParametersToRemove = argumentIndexOffset;
    if (this.returningName != null) {
        numParametersToRemove++;
    }
    if (this.throwingName != null) {
        numParametersToRemove++;
    }
    //去掉JoinPoint或ProceedingJoinPoint,和 returning,throwing 参数
    String[] pointcutParameterNames = new String[this.argumentNames.length - numParametersToRemove];
    //得到真正需要绑定的参数名和参数类型
    Class<?>[] pointcutParameterTypes = new Class<?>[pointcutParameterNames.length];
    Class<?>[] methodParameterTypes = this.aspectJAdviceMethod.getParameterTypes();

    int index = 0;
    for (int i = 0; i < this.argumentNames.length; i++) {
    	//过虑掉JoinPoint或ProceedingJoinPoint
        if (i < argumentIndexOffset) {
            continue;
        }
        //过虑掉 returning和throwing 参数
        if (this.argumentNames[i].equals(this.returningName) ||
            this.argumentNames[i].equals(this.throwingName)) {
            continue;
        }
        //设置真正需要绑定的参数名和参数类型
        pointcutParameterNames[index] = this.argumentNames[i];
        pointcutParameterTypes[index] = methodParameterTypes[i];
        index++;
    }
    //将参数名和参数类型分别保存到pointcutParameterNames,和pointcutParameterTypes中
    //这些参数在后面进行切面调用时,肯定用得到的
    this.pointcut.setParameterNames(pointcutParameterNames);
    this.pointcut.setParameterTypes(pointcutParameterTypes);
}

方法进行到这里,己经得到了 Advisor 类型,并且进行了方法参数绑定。

寻找匹配的增强器

        前面的函数中己经完成了所有的增强器的解析,但是对于所有的增强器来讲,并不一定都适用于当前的 Bean,还要获取出合适的增强器,也就是满足我们配置的通配符增强器,具体实现在findAdvisorsThatCanApply中。

AbstractAdvisorAutoProxyCreator.java
protected List<Advisor> findAdvisorsThatCanApply(
		List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
	ProxyCreationContext.setCurrentProxiedBeanName(beanName);
	try {
		return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
	}
	finally {
		ProxyCreationContext.setCurrentProxiedBeanName(null);
	}
}

继续看findAdvisorsThatCanApply。

AopUtils.java
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
	if (candidateAdvisors.isEmpty()) {
		return candidateAdvisors;
	}
	List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
	for (Advisor candidate : candidateAdvisors) {
		//引入增强(Introduction Advice)的概念:一个Java类,没有实现A接口,
		//在不修改Java类的情况下,使其具备A接口的功能。(非常强大有木有,A不需要动代码,就能有别的功能)
		//IntroductionAdvisor纯粹就是为Introduction而生的。
		//IntroductionAdvisor 和 PointcutAdvisor接口不同,它仅有一个类过滤器ClassFilter 而没有 MethodMatcher,
		//这是因为 `引介切面 的切点是类级别的,而 Pointcut 的切点是方法级别的(细粒度更细,所以更加常用)。
		//如果是引介增强,并且匹配成功
		if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
			eligibleAdvisors.add(candidate);
		}
	}
	//如果配置了引介增强,而其他的 pointcut的matchs匹配的是 maybe,直接返回匹配成功
	boolean hasIntroductions = !eligibleAdvisors.isEmpty();
	for (Advisor candidate : candidateAdvisors) {
		//引介增强己经处理
		if (candidate instanceof IntroductionAdvisor) {
			continue;
		}
		//处理普通的 bean增强
		if (canApply(candidate, clazz, hasIntroductions)) {
			eligibleAdvisors.add(candidate);
		}
	}
	return eligibleAdvisors;
}

        findAdvisorsThatCanApply函数的主要功能是寻找所有的增强器中适用于当前 class 的增强器,引介增强与普通增强处理是不一样的,所以分开处理,而对于真正的匹配在 canApply()中实现。

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
	if (advisor instanceof IntroductionAdvisor) {
		//引介增强对类级别的匹配
		return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
	}
	else if (advisor instanceof PointcutAdvisor) {
		PointcutAdvisor pca = (PointcutAdvisor) advisor;
		//如果是 PointcutAdvisor的实现类,则对方法级别匹配
		return canApply(pca.getPointcut(), targetClass, hasIntroductions);
	}
	else {
		return true;
	}
}
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
	Assert.notNull(pc, "Pointcut must not be null");
	//先对类级别匹配,如果不匹配返回 false,在这一步己经对切面表达式进行解析
	if (!pc.getClassFilter().matches(targetClass)) {
		return false;
	}

	MethodMatcher methodMatcher = pc.getMethodMatcher();
	IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
	if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
		introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
	}

	Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
	classes.add(targetClass);
	//对目标类中的每一个方法进行遍历
	for (Class<?> clazz : classes) {
		Method[] methods = clazz.getMethods();
		for (Method method : methods) {
			if ((introductionAwareMethodMatcher != null &&
					//目标方法和切面表达式进行匹配,如果匹配成功,则返回 true 
					introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
					methodMatcher.matches(method, targetClass)) {
				return true;
			}
		}
	}
	return false;
}
AspectJAwareAdvisorAutoProxyCreator.java
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
    List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors =
            new ArrayList<PartiallyComparableAdvisorHolder>(advisors.size());
    for (Advisor element : advisors) {
    	//初始化partiallyComparableAdvisors,DEFAULT_PRECEDENCE_COMPARATOR是AspectJPrecedenceComparator对象
        partiallyComparableAdvisors.add(
                new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR));
    }
    //开始真正的排序
    List<PartiallyComparableAdvisorHolder> sorted =
            PartialOrder.sort(partiallyComparableAdvisors);
    if (sorted != null) {
        List<Advisor> result = new ArrayList<Advisor>(advisors.size());
        for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
            result.add(pcAdvisor.getAdvisor());
        }
        return result;
    }
    else {
        return super.sortAdvisors(advisors);
    }
}
PartialOrder.java
public static List sort(List objects) {
    //如果切点个数是0个或者1个,没有必要排序
    if (objects.size() < 2) {
        return objects;
    }

    //创建新的比交对象 SortObject
    List<SortObject> sortList = new LinkedList<SortObject>(); // objects.size());
    for (Iterator i = objects.iterator(); i.hasNext();) {
        addNewPartialComparable(sortList, (PartialComparable) i.next());
    }

	//下面的代码,无非进行排序而已,分别获取objects[i]对应的切点而己
    final int N = objects.size();
    for (int index = 0; index < N; index++) {

        SortObject leastWithNoSmallers = null;

        for (Iterator i = sortList.iterator(); i.hasNext();) {
            SortObject so = (SortObject) i.next();
            if (so.hasNoSmallerObjects()) {
                if (leastWithNoSmallers == null || so.object.fallbackCompareTo(leastWithNoSmallers.object) < 0) {
                    leastWithNoSmallers = so;
                }
            }
        }
        if (leastWithNoSmallers == null) {
            return null;
        }
        removeFromGraph(sortList, leastWithNoSmallers);
        objects.set(index, leastWithNoSmallers.object);
    }
    return objects;
}
SortObject.java
private static void addNewPartialComparable(List graph, PartialComparable o) {
    SortObject so = new SortObject(o);
    for (Iterator i = graph.iterator(); i.hasNext();) {
        SortObject other = i.next();
        so.addDirectedLinks(other);
    }
    graph.add(so);
}
void addDirectedLinks(SortObject other) {
    int cmp = object.compareTo(other.object);
    if (cmp == 0) {
        return;
    }
    if (cmp > 0) {
        this.smallerObjects.add(other);
        other.biggerObjects.add(this);
    } else {
        this.biggerObjects.add(other);
        other.smallerObjects.add(this);
    }
}
PartiallyComparableAdvisorHolder.java
public int compareTo(Object obj) {
    Advisor otherAdvisor = ((PartiallyComparableAdvisorHolder) obj).advisor;
    return this.comparator.compare(this.advisor, otherAdvisor);
}
AspectJPrecedenceComparator.java
public int compare(Advisor o1, Advisor o2) {
    int advisorPrecedence = this.advisorComparator.compare(o1, o2);
    if (advisorPrecedence == 0 && declaredInSameAspect(o1, o2)) {
        advisorPrecedence = comparePrecedenceWithinAspect(o1, o2);
    }
    return advisorPrecedence;
}
OrderComparator.java
public int compare(Object o1, Object o2) {
	//这才是真正的匹配,我们在阅读 Spring 源码时,要注意一点,就是凡是 do 开头的方法才是真正做事情的方法,
	//其他的没有用 do 开头的,一般都是做一些辅助性的事情,比如初始化变量,参数较验等
    return doCompare(o1, o2, null);
}
private int doCompare(Object o1, Object o2, OrderSourceProvider sourceProvider) {
	//如果o1通知器实现了PriorityOrdered接口,p1为 true 
    boolean p1 = (o1 instanceof PriorityOrdered);
    boolean p2 = (o2 instanceof PriorityOrdered);
    //只有一个通知器实现了PriorityOrdered接口,而另一个通知器没有实现PriorityOrdered接口,才能快速比对
    if (p1 && !p2) {
        return -1;
    }
    else if (p2 && !p1) {
        return 1;
    }

    int i1 = getOrder(o1, sourceProvider);
    int i2 = getOrder(o2, sourceProvider);
    return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
}
private int getOrder(Object obj, OrderSourceProvider sourceProvider) {
    Integer order = null;
    if (sourceProvider != null) {
        Object orderSource = sourceProvider.getOrderSource(obj);
        if (orderSource != null && orderSource.getClass().isArray()) {
            Object[] sources = ObjectUtils.toObjectArray(orderSource);
            for (Object source : sources) {
                order = findOrder(source);
                if (order != null) {
                    break;
                }
            }
        }
        else {
            order = findOrder(orderSource);
        }
    }
    return (order != null ? order : getOrder(obj));
}
protected int getOrder(Object obj) {
    Integer order = findOrder(obj);
    return (order != null ? order :0x7fffffff);
}
AnnotationAwareOrderComparator.java
protected Integer findOrder(Object obj) {
    Integer order = super.findOrder(obj);
    if (order != null) {
        return order;
    }

    if (obj instanceof Class) {
        return OrderUtils.getOrder((Class<?>) obj);
    }
    else if (obj instanceof Method) {
        Order ann = AnnotationUtils.findAnnotation((Method) obj, Order.class);
        if (ann != null) {
            return ann.value();
        }
    }
    else if (obj instanceof AnnotatedElement) {
        Order ann = AnnotationUtils.getAnnotation((AnnotatedElement) obj, Order.class);
        if (ann != null) {
            return ann.value();
        }
    }
    else if (obj != null) {
        return OrderUtils.getOrder(obj.getClass());
    }

    return null;
}
protected Integer findOrder(Object obj) {
	//如果当前 advisor是 Ordered实现类,则调用 getOrder()方法
    return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null);
}
InstantiationModelAwarePointcutAdvisorImpl.java
public int getOrder() {
    return this.aspectInstanceFactory.getOrder();
}
LazySingletonAspectInstanceFactoryDecorator.java
public int getOrder() {
    return this.maaif.getOrder();
}
BeanFactoryAspectInstanceFactory.java
public int getOrder() {
    Class<?> type = this.beanFactory.getType(this.name);
    if (type != null) {
    	//如果当前类型是 Ordered 类的子类,并且是单例,直接调用该类的 getOrder()方法,
    	// 如:public class AspectJTest implements PriorityOrdered ,AspectJTest必需实现 getOrder()方法
        if (Ordered.class.isAssignableFrom(type) && this.beanFactory.isSingleton(this.name)) {
            return ((Ordered) this.beanFactory.getBean(this.name)).getOrder();
        }
        //调用工具类的 getOrder()方法
        return OrderUtils.getOrder(type, 0x7fffffff);
    }
    return 0x7fffffff;
}
OrderUtils.java
public static Integer getOrder(Class<?> type, Integer defaultOrder) {
	//如果切点所在类有@Order注解,则获取@Order的 value 值作为属性值
    Order order = AnnotationUtils.findAnnotation(type, Order.class);
    if (order != null) {
        return order.value();
    }
    //如果没有配置@Order接口,则看切点所在类配置了javax.annotation.Priority注解,如果有,则获取@Priority注解的值
    Integer priorityOrder = getPriority(type);
    if (priorityOrder != null) {
        return priorityOrder;
    }
    //如果还不满足,直接使用默认值吧,调用顺序排在最后
    return defaultOrder;
}

读者看到这里,肯定很晕,写的是什么东西?但是认真的读者肯定能发现其中的规律,

  1. 首先看当前切点是否是 PriorityOrdered的实现类,如果是,则排位靠前。
  2. 如果两个切点所在类都有@Order注解,value 值,越小,排位越靠前。
  3. 如果第一个切点所在类实现了PriorityOrdered接口,第二个切点所在类有@Order注解,则调用第一个切点所在类的 getOrder()方法获取返回值,与第二个切点所在类的@Order注解 value 值,进行比对,值越小,方法排位越靠前。
  4. 如果第一个切点所在类实现了PriorityOrdered接口,第二个切点所在类没有@Order注解,同时也没有实现PriorityOrdered接口,则获取第一个切点所在类的 getOrder()方法的返回值与第二个切点默认值0x7fffffff,进行比对,(而0x7fffffff是整数的最大值,我们配置的时候,一般不会配置这么大的值),比对值越小,方法排位越在前。
  5. 对于 getOrder()返回值相同的情况,该怎样么呢?下面的这个方法comparePrecedenceWithinAspect()就是来处理这种情况
AspectJPrecedenceComparator.java
private int comparePrecedenceWithinAspect(Advisor advisor1, Advisor advisor2) {
	//如果方法配置了@After,@AfterReturning,@AfterThrowing注解
    boolean oneOrOtherIsAfterAdvice =
            (AspectJAopUtils.isAfterAdvice(advisor1) || AspectJAopUtils.isAfterAdvice(advisor2));
    int adviceDeclarationOrderDelta = getAspectDeclarationOrder(advisor1) - getAspectDeclarationOrder(advisor2);
    
    if (oneOrOtherIsAfterAdvice) {
        if (adviceDeclarationOrderDelta < 0) {
            return 1;
        }
        else if (adviceDeclarationOrderDelta == 0) {
            return 0;
        }
        else {
            return -1;
        }
    }
    else {
        if (adviceDeclarationOrderDelta < 0) {
            return -1;
        }
        else if (adviceDeclarationOrderDelta == 0) {
            return 0;
        }
        else {
            return 1;
        }
    }
}

根据下图,我们来分析一下,对于 ExposeInvocationInterceptor,系统默认是首先调用,这个不用多解析,而下面的7个方法都是在一个切面类AspectJTest中定义,下面是源码中的顺序。
        abeforeTest()
        beforeTest()
        afterTest()
        bafterTest()
        AfterReturning()
        afterThrowing()
        aroundTest()
刚开始通过调用这个方法
Collections.sort(methods, METHOD_COMPARATOR);
将所有的方法排序 ,先按照注解顺序,Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class,如:配置了@Around注解的方法排在最前面,配置了@AfterReturning注解方法排在后面,如果同时配置了@Around注解,则按方法名称排序,a方法名的在前,b 方法名的在后,ab 方法名在前,ac 方法名在后。如果没有配置注解的方法,直接按照方法名排序,经过上面方法调用,方法排序变成这样
在这里插入图片描述
而此时此刻第一个方法 aroundTest()方法的getAspectDeclarationOrder(advisor)对应的值是0,而 abeforeTest()方法的getAspectDeclarationOrder(advisor)值是1,getAspectDeclarationOrder(advisor)的值【advisors.size()】,即所在集合的索引位置,经过上面的辅垫,我们终于知道
int adviceDeclarationOrderDelta = getAspectDeclarationOrder(advisor1) - getAspectDeclarationOrder(advisor2);这一行代码是什么意思了。也就是如果当前方法没有配置注解@After,@AfterReturning,@AfterThrowing,则依然按之前的顺序。所以得到

  1. aroundTest(),abeforeTest(),beforeTest()三个方法的顺序相对不变。
  2. 如果第一个切点方法配置了@After,而第二个切点方法没有配置,则第一个切点方法排位靠前。
  3. 如果第一个切点方法配置了@After,而第二个切点方法也配置了@After,按照方法名降序,如 a ,b 方法,b 方法靠前,a 方法靠后,ab ,ac 方法,ac 方法靠前,ab 方法排位靠后。
  4. 对于 a,b,c 方法分别配置了注解 @After, @AfterReturning, @AfterThrowing,则 c 方法最前,b 方法中间,a 方法最后。

经过上面分析,我们终于知道下图方法顺序是怎样来了的【这个顺序非常重要,直接关系到切点调用顺序】

        @AfterThrowing(pointcut = “test()”, throwing = “e”)
        public void afterThrowing(Exception e) {}
        @AfterReturning(“test()”)
        public void AfterReturning() {}
        @After(“test()”)
        public void bafterTest() {}
        @After(“test()”)
        public void afterTest() {}
        @Around(“test()”)
        public Object aroundTest(ProceedingJoinPoint p) {}
        @Before(“test()”)
        public void abeforeTest(JoinPoint jp) { }
        @Before(“test()”)
        public void beforeTest() { }
在这里插入图片描述

创建代理

        在这个方法中的两个 matchs,之前花了大量的时间来分析这两个方法,这里就不再多说了,到这里我们来总结一下,其实,上面的代码,看上去写了一大堆,其实,方法的原理很简单,就是 Spring 先去找到所有配置了 Aspect.class 注解的类,再在该类上找到所有配置了Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class注解的方法,将每个配置了以上注解的方法封装成一个 Advisor 对象,再调用 Advisor 的 canApply 方法,判断目标类方法是否和 Advisor 表达式匹配,如果匹配,则保存到 Advisor集合中,再对集合进行排序,排序的过程,会考虑到切点所在类是否配置了@Order注解。在代码查找的过程中,Spring加入大量缓存的使用,不过,这些也只是锦上添花而已,核心逻辑还是不变的。在获取了所有对应的bean 的增强后,便可以进行代理创建了。

AbstractAutoProxyCreator.java
protected Object createProxy(
		Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
	ProxyFactory proxyFactory = new ProxyFactory();
	//获取当前类中相关属性
	proxyFactory.copyFrom(this);
	//判断用户有没有配置proxyTargetClass
	if (!proxyFactory.isProxyTargetClass()) {
		//目标 bean 中是否配置了preserveTargetClass,如果配置了,使用cglib代理
		if (shouldProxyTargetClass(beanClass, beanName)) {
			proxyFactory.setProxyTargetClass(true);
		}
		else {
			//评估接口,如果当前类有接口,则加入到advisor 的interfaces中,
			//如果没有,设置proxyTargetClass为 true,强制使用 CGlib 代理
			evaluateProxyInterfaces(beanClass, proxyFactory);
		}
	}
	//将注解配置的通知器和普通的通知器合并
	Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
	//将当前通知器加入到代理工厂的 advisors中
	for (Advisor advisor : advisors) {
		//将当前与类匹配的所有通知器加入到代理工厂的 advisors 中
		proxyFactory.addAdvisor(advisor);
	}
	//设置目标类为源类
	proxyFactory.setTargetSource(targetSource);
	//定制代理
	customizeProxyFactory(proxyFactory);
	//用来控制代理工厂被配置之后,是否还允许修改通知
	//缺省值为false(即在代理被配置之后,不允许修改代理的配置)
	proxyFactory.setFrozen(this.freezeProxy);
	if (advisorsPreFiltered()) {
		proxyFactory.setPreFiltered(true);
	}
	//获取代理类
	return proxyFactory.getProxy(getProxyClassLoader());
}

        对于代理类的创建及处理,Spring 委托给了ProxyFactory去处理,而在此函数中主要是对 ProxyFactory 的初始化操作,进而对真正的创建代理做准备,这些初始化操作包括如下内容。

  1. 获取当前类中的属性。
  2. 添加代理接口。
  3. 封装 Advisor并加入到 ProxyFactory 中。
  4. 设置要代理的类。
  5. 当然在 Spring 中还为子类提供了定制的函数 customizaProxyFactory,子类可以在此函数中进行对 ProxyFactory 的进一步封装。
  6. 进行获取代理操作。

        其中,封装 Advisor 并加入到 ProxyFactory 中以及创建代理是两个相对繁琐的过程,可以通过 ProxyFactory 提供 addAdvisor方法直接将增强器置入代理创建工厂中,但是将拦截器封装为增强器还是需要一定的逻辑的。

AbstractAutoProxyCreator.java
protected Advisor[] buildAdvisors(String beanName, Object[] specificInterceptors) {
	//解析注册的所有interceptorName
	Advisor[] commonInterceptors = resolveInterceptorNames();
	List allInterceptors = new ArrayList();
	if (specificInterceptors != null) {
		allInterceptors.addAll(Arrays.asList(specificInterceptors));
		if (commonInterceptors != null) {
			if (this.applyCommonInterceptorsFirst) {
				//加入拦截器
				allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
			}
			else {
				allInterceptors.addAll(Arrays.asList(commonInterceptors));
			}
		}
	}
	if (logger.isDebugEnabled()) {
		int nrOfCommonInterceptors = (commonInterceptors != null ? commonInterceptors.length : 0);
		int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
		logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
				" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
	}

	Advisor[] advisors = new Advisor[allInterceptors.size()];
	for (int i = 0; i < allInterceptors.size(); i++) {
		//拦截器进行封装转化为 Advisor
		advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
	}
	return advisors;
}
DefaultAdvisorAdapterRegistry.java
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
	//如果要封装的对象本身就是 Advisor 类型,那么无须再做过多处理
	if (adviceObject instanceof Advisor) {
		return (Advisor) adviceObject;
	}
	//因为此封装方法只对 Advisor 与 Advice两种类型的数据有效,如果不是将不能封装
	if (!(adviceObject instanceof Advice)) {
		throw new UnknownAdviceTypeException(adviceObject);
	}
	Advice advice = (Advice) adviceObject;
	if (advice instanceof MethodInterceptor) {
		//如果是 MethodInterceptor 类型则使用 DefaultPointAdvisor封装
		return new DefaultPointcutAdvisor(advice);
	}
	for (AdvisorAdapter adapter : this.adapters) {
		//如果存在 Advisor 的适配器,那么同样需要进行封装
		if (adapter.supportsAdvice(advice)) {
			return new DefaultPointcutAdvisor(advice);
		}
	}
	throw new UnknownAdviceTypeException(advice);
}

        由于 Spring 中涉及过多拦截器,增强器,增强方法等方式来对逻辑进行增强,所以非常有必要统一封装 Advisor 来进行代理的创建,完成增强的封装过程,那么解析最重要的一步就是代理的创建与获取了。

ProxyFactory.java
public Object getProxy(ClassLoader classLoader) {
	return createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
	if (!this.active) {
		activate();
	}
	return getAopProxyFactory().createAopProxy(this);
}
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.");
		}
		//如果目标类是接口或者是代理类,则使用 JDK动态代理,否则使用 Cglib代理
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
			return new JdkDynamicAopProxy(config);
		}
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		return new JdkDynamicAopProxy(config);
	}
}
public Object getProxy(ClassLoader classLoader) {
	if (logger.isDebugEnabled()) {
		logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
	}

	try {
		Class<?> rootClass = this.advised.getTargetClass();
		Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

		Class<?> proxySuperClass = rootClass;
		if (ClassUtils.isCglibProxyClass(rootClass)) {
			proxySuperClass = rootClass.getSuperclass();
			Class<?>[] additionalInterfaces = rootClass.getInterfaces();
			for (Class<?> additionalInterface : additionalInterfaces) {
				this.advised.addInterface(additionalInterface);
			}
		}
		//验证该类,并根据需要编写日志消息。
		validateClassIfNecessary(proxySuperClass, classLoader);

		Enhancer enhancer = createEnhancer();
		if (classLoader != null) {
			enhancer.setClassLoader(classLoader);
			if (classLoader instanceof SmartClassLoader &&
					((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
				enhancer.setUseCache(false);
			}
		}
		enhancer.setSuperclass(proxySuperClass);
		enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
		enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
		enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class));
		//设置拦截器
		Callback[] callbacks = getCallbacks(rootClass);
		Class<?>[] types = new Class<?>[callbacks.length];
		for (int x = 0; x < types.length; x++) {
			types[x] = callbacks[x].getClass();
		}
		// 仅在上述getCallbacks调用之后,此时才会填充fixedInterceptorMap,
		//ProxyCallbackFilter这个非常重要,这个是 Spring aop 实现的关键类,
		enhancer.setCallbackFilter(new ProxyCallbackFilter(
				this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
		enhancer.setCallbackTypes(types);

		// 生成代理类并创建代理实例
		return createProxyClassAndInstance(enhancer, callbacks);
	}
	catch (CodeGenerationException ex) {
		throw new AopConfigException("Could not generate CGLIB subclass of class [" +
				this.advised.getTargetClass() + "]: " +
				"Common causes of this problem include using a final class or a non-visible class",
				ex);
	}
	catch (IllegalArgumentException ex) {
		throw new AopConfigException("Could not generate CGLIB subclass of class [" +
				this.advised.getTargetClass() + "]: " +
				"Common causes of this problem include using a final class or a non-visible class",
				ex);
	}
	catch (Exception ex) {
		// TargetSource.getTarget() failed
		throw new AopConfigException("Unexpected AOP exception", ex);
	}
}

在上面方法中有一个 setCallbackTypes 方法,这个方法非常重要,这个方法向系统设置了动态代理拦截器,后面将根据方法信息,来动态匹配。

CglibAopProxy.java
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
    // bean 的定义中是否配置了 <aop:aspectj-autoproxy expose-proxy="true">
    // 标记代理对象是否应该被aop框架通过AopContext以ThreadLocal的形式暴露出去。
	// 当一个代理对象需要调用它自己的另外一个代理方法时,这个属性将非常有用。默认是是false,以避免不必要的拦截。
    boolean exposeProxy = this.advised.isExposeProxy();
    // 标记该配置是否需要被冻结,如果被冻结,将不可以修改增强的配置。
	// 如果该值为true,那么代理对象的生成的各项信息配置完成,则不容许更改,
	// 如果ProxyFactory设置完毕,该值为true,则不能对Advice进行改动,可以优化代理对象生成的性能。默认情况下该值为false
    boolean isFrozen = this.advised.isFrozen();
    //在本例中的TargetSource是AbstractAutoProxyCreator的wrapIfNecessary方法中 new SingletonTargetSource()对象,
    //因此,SingletonTargetSource的 isStatic 是 true
    boolean isStatic = this.advised.getTargetSource().isStatic();

    //将拦截器封装在DynamicAdvisedInterceptor中
    Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

    
    Callback targetInterceptor;
    if (exposeProxy) {
        targetInterceptor = isStatic ?
                new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
                new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
    }
    else {
        targetInterceptor = isStatic ?
                new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
                new DynamicUnadvisedInterceptor(this.advised.getTargetSource());
    }

    //如果是单例,isStatic是静态的
    Callback targetDispatcher = isStatic ?
            new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();
	//主拦截器链
    Callback[] mainCallbacks = new Callback[]{
    	//将拦截器链加入到Callback中
        aopInterceptor, 
        targetInterceptor, 
        new SerializableNoOp(),
        targetDispatcher, this.advisedDispatcher,
        new EqualsInterceptor(this.advised),
        new HashCodeInterceptor(this.advised)
    };

    Callback[] callbacks;

    //如果是单例,又不可以修改增强配置
    if (isStatic && isFrozen) {
        Method[] methods = rootClass.getMethods();
        Callback[] fixedCallbacks = new Callback[methods.length];
        this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length);

       	//创建fix拦截器链
        for (int x = 0; x < methods.length; x++) {
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
            fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
                    chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
            this.fixedInterceptorMap.put(methods[x].toString(), x);
        }

        //合并拦截器链,将固定拦截器链放到调用链后面,如果既有动态拦截器链和静态拦截器链,先调用动态,再调用静态
        callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
        System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
        System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
        this.fixedInterceptorOffset = mainCallbacks.length;
    }
    else {
    	//直接获取动态拦截器链
        callbacks = mainCallbacks;
    }
    return callbacks;
}

        在 getCallback 中Spring 考虑了很多情况,但是对于我们来说,只需要理解最常用的就可以了,比如将 advised 属性封装在 DynamicAdvisedInterceptor 并加入到 callback 中,这么做的目的是什么呢?如何调用呢?在前面的示例中,我们了解到CGLIB 对于方法的拦截是通过将自定义拦截器(实现 MethodInterceptor 接口)加入 Callback 中并调用代理时直接激活拦截器中的 intercept 方法来实现的,那么在 getCallback 中正是实现这样一个目的,DynamicAdvisedInterceptor 继承自MethodInterceptor,加入Callback 中后,在再次调用代理时会直接调用 DynamicAdvisedInterceptor中的 intercept 方法,由此推断,对于 CGLIB 方式实现的代理,其核心逻辑必然在 DynamicAdvisedInterceptor 中的 Intercept 中。

在这里插入图片描述

ObjenesisCglibAopProxy.java

protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
	Class<?> proxyClass = enhancer.createClass();
	Object proxyInstance = null;
	if (objenesis.isWorthTrying()) {
		try {
			//如果没有配置spring.objenesis.ignore,则创建代理实现
			proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
		}
		catch (Throwable ex) {
			logger.debug("Unable to instantiate proxy using Objenesis, " +
					"falling back to regular proxy construction", ex);
		}
	}

	if (proxyInstance == null) {
		try {
			//通过构造函数创建代理实例
			proxyInstance = (this.constructorArgs != null ?
					proxyClass.getConstructor(this.constructorArgTypes).newInstance(this.constructorArgs) :
					proxyClass.newInstance());
		}
		catch (Throwable ex) {
			throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
					"and regular proxy instantiation via default constructor fails as well", ex);
		}
	}
	((Factory) proxyInstance).setCallbacks(callbacks);
	return proxyInstance;
}

在创建代理类的过程非常复杂,这里就不做过多分析,我们只分析在 Spring 中代理到底做了哪些事情。
在这里插入图片描述
我们知道在创建代理过程中,设置了setCallbackTypes回调类型,在 cglib 中是如何调用的,我也不去做详细分析了,但是其主要表现是当CglibAopProxy代理方法accept(method),根据方法类型,如果方法返回0,将使用DynamicAdvisedInterceptor拦截器,如果返回6,则使用HashCodeInterceptor拦截器。

        types[0]:DynamicAdvisedInterceptor
        types[1]:StaticUnadvisedExposedInterceptor
        types[2]:SerializableNoOp
        types[3]:StaticDispatcher
        types[4]:AdvisedDispatcher
        types[5]:EqualsInterceptor
        types[6]:HashCodeInterceptor
下面我们来分析CglibAopProxy的 accept 方法

CglibAopProxy.java

public int accept(Method method) {
    if (AopUtils.isFinalizeMethod(method)) {
        logger.debug("Found finalize() method - using NO_OVERRIDE");
        //如果方法名为finalize,并且方法参数个数为0,则使用SerializableNoOp拦截器
        return 2;			
    }
   
    // opaque :该属性用于空值生成的代理对象是否可以强制转型为Advised,默认值为false,
    // 表示任何生成的代理对象都可以强制转换成Advised,true是不可以,可以通过Adviced查询代理对象的一些状态
    if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
            method.getDeclaringClass().isAssignableFrom(Advised.class)) {
        if (logger.isDebugEnabled()) {
            logger.debug("Method is declared on Advised interface: " + method);
        }
        //如果opaque属性为 false,任何生成的代理对象都可以强制转换成Advised,
        //并且该方法所在类是一个接口,并且该方法所在类是 Advised 子孙类,将使用AdvisedDispatcher转发器
        return 4;
    }
    //equals方法处理
    if (AopUtils.isEqualsMethod(method)) {
        logger.debug("Found 'equals' method: " + method);
        //如果方法是equals方法,并且参数个数是1,并且第一个参数是 Object 类型,将使用EqualsInterceptor拦截器
        return 5;
    }
    //hashCode 方法处理
    if (AopUtils.isHashCodeMethod(method)) {
        logger.debug("Found 'hashCode' method: " + method);
        //如果方法名是hashCode,并且方法参数个数为0,则使用HashCodeInterceptor拦截器
        return 6;
    }
    Class<?> targetClass = this.advised.getTargetClass();
    //获取方法的拦截器链,这个方法特别重要,是aop方法拦截的关键
    List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    //如果拦截器链不为空
    boolean haveAdvice = !chain.isEmpty();
    //如果用户配置了expose-proxy="true",强制使用动态代理 ,比如 AService中有方法 a和b,在 a方法里调用 b方法,
    默认情况下,是不会对 b 方法拦截的,但是配置了expose-proxy="true",将会对 b方法实现拦截 
    boolean exposeProxy = this.advised.isExposeProxy();
    //如果是单例的话,默认为 true 
    boolean isStatic = this.advised.getTargetSource().isStatic();
    // 标记该配置是否需要被冻结,如果被冻结,将不可以修改增强的配置。
	// 如果该值为true,那么代理对象的生成的各项信息配置完成,则不容许更改,如果ProxyFactory设置完毕,该值为true,
	// 则不能对Advice进行改动,可以优化代理对象生成的性能。默认情况下该值为false 
    boolean isFrozen = this.advised.isFrozen();
    //如果拦截器链中有 advisor 或者可以对代理对象生成的各项信息配置进行更改
    if (haveAdvice || !isFrozen) {
        if (exposeProxy) {
            if (logger.isDebugEnabled()) {
                logger.debug("Must expose proxy on advised method: " + method);
            }
            //如果expose-proxy="true",直接使用DynamicAdvisedInterceptor
            return 0;
        }
        String key = method.toString();
        //如果是单例,并且是不可以对各项配置信息修改,而且固定拦截器中还有该方法的名称,从固定拦截器集合中获取拦截器
        if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Method has advice and optimisations are enabled: " + method);
            }
            int index = this.fixedInterceptorMap.get(key);
            return (index + this.fixedInterceptorOffset);
        }
        else {
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to apply any optimisations to advised method: " + method);
            }
            //还是使用DynamicAdvisedInterceptor拦截
            return 0;
        }
    }
    else {

        if (exposeProxy || !isStatic) {
        	//如果expose-proxy="true",并且不是静态的,使用StaticUnadvisedExposedInterceptor拦截器
            return 1;
        }
        Class<?> returnType = method.getReturnType();
        if (targetClass == returnType) {
            if (logger.isDebugEnabled()) {
                logger.debug("Method " + method +
                        "has return type same as target type (may return this) - using INVOKE_TARGET");
            }
            //方法的返回值类型和目标值类型相同,则使用StaticUnadvisedExposedInterceptor拦截器
            return 1;
        }
        else if (returnType.isPrimitive() || !returnType.isAssignableFrom(targetClass)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Method " + method +
                        " has return type that ensures this cannot be returned- using DISPATCH_TARGET");
            }
            //如果返回值类型是boolean,character,byte,short,int,long,Float,Double,Void 类型,并且目标值类型不是返回值类型的子孙类 
            //则使用StaticDispatcher
            return 3;
        }
        else {
            if (logger.isDebugEnabled()) {
                logger.debug("Method " + method +
                        "has return type that is assignable from the target type (may return this) - " +
                        "using INVOKE_TARGET");
            }
            //如果是其他情况将使用StaticUnadvisedExposedInterceptor拦截器
            return 1;
        }
    }
}

AdvisedSupport.java

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
    MethodCacheKey cacheKey = new MethodCacheKey(method);
    List<Object> cached = this.methodCache.get(cacheKey);
    if (cached == null) {
    	//获取当前方法的拦截器链
        cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
                this, method, targetClass);
        this.methodCache.put(cacheKey, cached);
    }
    return cached;
}

DefaultAdvisorChainFactory.java
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
        Advised config, Method method, Class<?> targetClass) {
    
    List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
    Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
    //当前类是否匹配引介增强
    boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
    AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

    for (Advisor advisor : config.getAdvisors()) {
        if (advisor instanceof PointcutAdvisor) {
            //如果当前 advisor是 PointcutAdvisor
            PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
            //下面的这个是快速匹配,查看当前类和切点表达式是否匹配,如果不匹配,则略过
            if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
            	// 获取当前通知器的方法拦截器,如果没有配置@Before,@AfterReturning,@AfterThrowing注解的,
            	// Advisor 即是拦截器本身,如果是配置了这些注解的,将用new MethodBeforeAdviceInterceptor(advice),
            	// new AfterReturningAdviceInterceptor(advice),new ThrowsAdviceInterceptor(advisor.getAdvice())包装一下
                MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                //切点表达式与方法精确匹配
                if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
                	//这个方法有点意思,也就是判断当前切点表达式解析出来的对象中是否有WithinAnnotationPointcut类型,
                	WithinCodeAnnotationPointcut,AnnotationPointcut,ArgsAnnotationPointcut,ArgsPointcut,
                	CflowPointcut,IfPointcut,NotAnnotationTypePattern,NotPointcut,ThisOrTargetAnnotationPointcut,
                	ThisOrTargetPointcut。
                	//这句话是什么意思呢?比如我们切点表达式是execution(* com..test65_2.*.*(..)) && args(x,y)
                	//在这个表达式args(x,y),而这个表达式最终会被解析成ArgsPointcut对象,而 Spring发现表达式解析出来的对象中有ArgsPointcut
                	//那么isRuntime就返回 true 了
                    if (mm.isRuntime()) {
                    	//将方法拦截器加入到拦截器链中
                        for (MethodInterceptor interceptor : interceptors) {
                            interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                        }
                    }
                    else {
                        interceptorList.addAll(Arrays.asList(interceptors));
                    }
                }
            }
        }
        //如果通知器是引介增强
        else if (advisor instanceof IntroductionAdvisor) {
            IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
            if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
                Interceptor[] interceptors = registry.getInterceptors(advisor);
                interceptorList.addAll(Arrays.asList(interceptors));
            }
        }
        else {
        	//如果在其他切点类型,则从注册器中获取拦截器
            Interceptor[] interceptors = registry.getInterceptors(advisor);
            interceptorList.addAll(Arrays.asList(interceptors));
        }
    }
    return interceptorList;
}

        到这里,我们终于解析完动态代理的创建过程,当代理创建完以后,方法拦截器链保存到了advised的methodCache中,当方法调用时,使用DynamicAdvisedInterceptor拦截器逐个调用拦截器链,那这个调用过程在下一篇博客中再来细细道来。
        到此时己经完成了代理的创建,不管我们之前是否阅读过 Spring 的源码,但是或多或少听过 Spring 的代理中 JDKProxy 的实现和 CglibProxy 的实现,Spring 是如何选取的呢?网上的介绍很多,现在我们就从源码的解析来分析,看看到底 Spring 是如何选择代理方式的呢?

  • optimize: 用来控制通过 CGLIB 创建的代理是否使用激进的优化策略,除非完全了解AOP代理是如何处理优化的,否则不推荐用户使用这个设置,目前这个属性仅用于 CGLIB 代理 ,对于 JDK 动态代理(默认代理)无效。
  • proxyTargetClass:这个属性为 true时,目标类本身被代理而不是目标接口类接口,如果这个属性值被设置为 true,CGLIB代理将被创建,设置方式<aop:aspectj-autoproxy proxy-target-class=“true” />
  • hasNoUserSuppliedProxyInterfaces:是否存在代理接口。

下面是对 JDK与 Cglib 方式总结。

  • 如果目标对象实现了接口,默认情况下会采用 JDK 动态代理实现 AOP 。
  • 如果目标对象实现了接口,可以强制使用 CGLIB 实现 AOP
  • 如果目标对象没有实现接口,必需采用 CGLIB 库,Spring会自动在 JDK动态代理和 CGLIB之间转换。

如何强制使用 CGLIB 实现 AOP ?

  • 添加 CGLIB库,Spring_HOME/cglib/*.jar
  • 在 Spring 配置文件中加入了<aop:aspectj-autoproxy proxy-target-class=“true”/>

JDK动态代理和 CGLIB 字节码生成的区别?

  • JDK 动态代理只能对实现了接口的类生成代理,而不能针对类。
  • CGLIB 是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成 final。

过程:

1)postProcessAfterInitialization():bean 的创建过程中,initializeBean()的后处理器
	1)wrapIfNecessary():早期代理引用中如果不包含当前 bean 的代理,则调用此方法。
		1)getAdvicesAndAdvisorsForBean():获取 bean 的通知器
			1)findEligibleAdvisors():发现当前bean 的通知器
				1)findCandidateAdvisors():发现系统所有的 Advisor
					1)beanNamesForTypeIncludingAncestors(): 发现所有Advisor类型的 bean
					2)buildAspectJAdvisors():构建所有的isAspect的 Advisor
						1)getAdvisors(): 获取所有的 Advisor
							1)getAdvisor():获取 advisor 
								1)getPointcut():获取切点 
									1)findAspectJAnnotationOnMethod(): 发现切面注解
									2)new AspectJExpressionPointcut():构建切点表达式对象
								2)new InstantiationModelAwarePointcutAdvisorImpl(): 创建 advisor
									1)instantiateAdvice():初始化 advice
										1)getAdvice(): 从工厂方法中获取 Advice 
											1)new AspectJMethodBeforeAdvice():如果方法配置了@Before 注解
											2)new AspectJAfterAdvice(): 如果方法配置了@After 注解
											3)new AspectJAfterReturningAdvice(): 如果方法配置了@AfterReturning注解
												1)setReturningName():设置返回值名称
											4)new AspectJAfterThrowingAdvice(): 如果配置了@AfterThrowing注解
												1)setThrowingName():设置异常属性名
											5)new AspectJAroundAdvice(): 如果配置了@Around注解
											6)calculateArgumentBindings(): 绑定方法参数名和参数类型
				2) findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz):发现匹配当前类方法的 Advisor
					1)canApply(): 判断 Advisor是否和当前类匹配
						1)matches(): 匹配成功,返回 TRUE,将当前 Advisor 加入到匹配列表中
				3) extendAdvisors():
					1)makeAdvisorChainAspectJCapableIfNecessary(): 创建通知器链
						1) new ExposeInvocationInterceptor(): 将ExposeInvocationInterceptor的 Advisor 加入到advisors中
				4)sortAdvisors():对 Advisors 排序。
		2)createProxy():创建代理 
			1) buildAdvisors(beanName, specificInterceptors):通过 bean 名称和拦截器构建Advisor
				1) resolveInterceptorNames(): 获取系统定义的拦截器
				2)addAll() : 将系统拦截器和用户自定义拦截器合并
			2) createAopProxy(): 创建 aop 代理 
				1)getAopProxyFactory():获取代理工厂
					1)JdkDynamicAopProxy() : 创建 jdk 代理
					2)ObjenesisCglibAopProxy(): 创建 cglib 代理 ,如没有接口,直接创建 Cglib 代理
				2)createAopProxy():创建代理
					1)getProxy():获取代理
						1)getTargetClass():获取目标类
						2)createEnhancer():创建 Enhancer
						3)createProxyClassAndInstance():创建代理实例
							1)createClass():创建代理类
								1)accept(Method method): 代理回调
									1)getInterceptorsAndDynamicInterceptionAdvice(): 获取拦截器链
										1)matches():如果目标方法和 Advisor切面表达式匹配,则加入到目标方法的调用链中
							2)newInstance(): 创建实例
							

我们经过上面的分析,Spring在创建代理的过程,写了大量的代码。但是理清思路后,发现还是简单的。

  1. Spring 遍历所有的 bean,找到配置了@Aspect 注解的类
  2. 从配置了@Aspect 注解的类中拿到所有配置了@Around …@Before 注解的方法,并封装成相应的 Advisor
  3. 遍历目标类的所有方法,与 Advisor 逐一进行匹配,如果匹配成功,创建动态代理 。

到这里,我们己经对于bean 的创建己经分析完成,如果目标类中有方法和 Advisor匹配,则创建动态代理 ,存储于容器中。最终,通过 getBean 得到的是代理类,代理是如何逐一调用各个通知器的,在下一篇博客中再来分析 。

思考?

Aservice.java

public interface Aservice  {
    void b (String x,String y);
}

AserviceImpl.java

@Service
public class AserviceImpl implements Aservice {
    @Override
    public void b(String x,String y ) {
        System.out.println("print x=" + x + ",y="+y);
    }
}

AspectJTest.java

@Aspect
public class AspectJTest {

    @Pointcut("execution(* com.spring_1_100.test_61_70.test65.*.*(..)) && args(..)")
    public void test() {

    }

    @Before("test()")
    public void abeforeTest(JoinPoint jp) {
        System.out.println("abeforeTest" + JSON.toJSONString(jp.getArgs()));
    }


    @Before("test()")
    public void beforeTest() {
        System.out.println("beforeTest");
    }


    @After("test()")
    public void afterTest() {
        System.out.println("afterTest()");
    }


    @After("test()")
    public void bafterTest() {
        System.out.println("bafterTest()");
    }


    @AfterReturning("test()")
    public void AfterReturning() {
        System.out.println("AfterReturning()");
    }

    @AfterThrowing(pointcut = "test()", throwing = "e")
    public void afterThrowing(Exception e) {
        System.out.println("例外通知");
        System.out.println(e.getMessage());
    }

    @Around("test()")
    public Object aroundTest(ProceedingJoinPoint p) {
        System.out.println("around before1");
        Object o = null;
        try {
            o = p.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("around after1");
        return o;
    }

}

spring65.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">


    <aop:aspectj-autoproxy expose-proxy="true"></aop:aspectj-autoproxy>
    <context:annotation-config></context:annotation-config>
    <context:component-scan base-package="com.spring_1_100.test_61_70.test65"></context:component-scan>

    <bean id="aservice" class="com.spring_1_100.test_61_70.test65.AserviceImpl"></bean>
    <bean class="com.spring_1_100.test_61_70.test65.AspectJTest"></bean>

</beans>

测试:

public static void main(String[] args) {
    ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring_1_100/config_61_70/spring65.xml");
    Aservice service =(Aservice) ac.getBean("aservice");
    service.b("quyixiao","hukaiming");
}

结果是什么?为什么?

本文的github地址是
https://github.com/quyixiao/spring_tiny/tree/master/src/main/java/com/spring_101_200/test_111_120/test_117_excution/excution1

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值