你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

Spring源码分析第三弹 - AOP切面编程分析

2021/12/27 14:03:53

终于到AOP了,前面没看懂的一定跟着代码多看,不然本篇文章容易迷路!
话不多说,万变不离其宗,先上图。

AOP时序图

AOP时序图

源码分析

1.初始化阶段 -> 匹配切点的方法

  • 回到上篇文章中的AbstractAutowireCapableBeanFactory.doCreateBean主要看依赖注入后面的代码
//找到这里
//依赖注入
populateBean(beanName, mbd, instanceWrapper);
//初始化bean里面的初始方法 AOP切面入口 本文主要看这个
exposedObject = initializeBean(beanName, exposedObject, mbd);

//初始容器时创建的Bean对象,为其添加BeanPostProcessor后置处理器
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			invokeAwareMethods(beanName, bean);
			return null;
		}, getAccessControlContext());
	}
	else {
        //调用所有实现BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口方法回调
        //为Bean实例对象包装相关属性,如名称,类加载器,所属容器等信息
		invokeAwareMethods(beanName, bean);
	}

	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
        //调用回调方法,为Bean实例初始化前做一些处理
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}

	try {
        //文件中通过init-method属性指定的 或者 @PostConstruct
        //还有一些实现InitializingBean 会调用后置通知 afterPropertiesSet
        //MVC mapping在这里回调触发 下一篇MVC时讲解
		invokeInitMethods(beanName, wrappedBean, mbd);
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				(mbd != null ? mbd.getResourceDescription() : null),
				beanName, "Invocation of init method failed", ex);
	}
	if (mbd == null || !mbd.isSynthetic()) {
        //调用回调方法,为Bean实例初始化之后做一些处理 AOP代理主要走这个
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}
  		//返回对象
	return wrappedBean;
}



//调用BeanPostProcessor后置处理器实例对象初始化之后的处理方法
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
		throws BeansException {

	Object result = existingBean;
	//遍历容器为所创建的Bean回调所有实现了BeanPostProcessor接口后置处理器
	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
		//为Bean实例对象在初始化之后做一些自定义的处理操作 接下来走这个
		Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}
  • 接下来就到了spring-aop包下的AbstractAutoProxyCreator#postProcessAfterInitialization -> wrapIfNecessary
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.
	//如果存在advice 就创建代理类 先看获取advices链,再看创建代理对象
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	//如果这个数组不等于null
	//protected static final Object[] DO_NOT_PROXY = null;
	if (specificInterceptors != DO_NOT_PROXY) {
		//标识这个bean被有advice
		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;
}
  • 接下来看获取拦截器链advices的逻辑,往下到AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean
protected Object[] getAdvicesAndAdvisorsForBean(
		Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
	//找到符合资格的拦截器
	List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
	if (advisors.isEmpty()) {
		return DO_NOT_PROXY;
	}
	return advisors.toArray();
}

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    //加载当前已配置的AOP列表
	List<Advisor> candidateAdvisors = findCandidateAdvisors();
    //根据beanName去匹配 下面简单分析一下这个
	List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
	extendAdvisors(eligibleAdvisors);
	if (!eligibleAdvisors.isEmpty()) {
        //排序
		eligibleAdvisors = sortAdvisors(eligibleAdvisors);
	}
    //返回执行责任链
	return eligibleAdvisors;
}
  • findAdvisorsThatCanApply 一直往下到 AopUtils.canApply
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
	Assert.notNull(pc, "Pointcut must not be null");
	if (!pc.getClassFilter().matches(targetClass)) {
		return false;
	}

	MethodMatcher methodMatcher = pc.getMethodMatcher();
	if (methodMatcher == MethodMatcher.TRUE) {
		// No need to iterate the methods if we're matching any method anyway...
		return true;
	}

	IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
	if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
		introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
	}

	Set<Class<?>> classes = new LinkedHashSet<>();
	if (!Proxy.isProxyClass(targetClass)) {
		classes.add(ClassUtils.getUserClass(targetClass));
	}
	classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

	for (Class<?> clazz : classes) {
        //获取所有的方法
		Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
		for (Method method : methods) {
            //断点调试走introductionAwareMethodMatcher.matches 接下来看这里
			if (introductionAwareMethodMatcher != null ?
					introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
					methodMatcher.matches(method, targetClass)) {
				return true;
			}
		}
	}
	return false;
}
  • introductionAwareMethodMatcher.matches -> AspectJExpressionPointcut.getShadowMatch
//找到这行 通过AOP规则验证这个方法是否满足切点
shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);

如果满足当前配置的切点,则在AbstractAutoProxyCreator#wrapIfNecessary创建代理对象并返回,初始化阶段到这里就完成了,接下来继续分析创建代理源码,也就是代码织入阶段

2.代码织入阶段 ->创建动态代理

  • 回到AbstractAutoProxyCreator.wrapIfNecessary
//找到这一段
//获取拦截器链
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;
}

//创建代理对象
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);
    //原始class对象的信息 封装了一层SingletonTargetSource
    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }
	//创建代理-> 这里有两种创建代理的方法 CGLIB 和JDK 我们这里挑 JdkDynamicAopProxy看
    return proxyFactory.getProxy(getProxyClassLoader());
}
  • 接下来到ProxyFactory#getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
	return createAopProxy().getProxy(classLoader);
}

//createAopProxy -> ProxyCreatorSupport#createAopProxy
protected final synchronized AopProxy createAopProxy() {
	if (!this.active) {
		activate();
	}
	//传的是this
	return getAopProxyFactory().createAopProxy(this);
}

//得到jdk或者Cglib对象
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	if (!NativeDetector.inNativeImage() &&
			(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)) {
			//通过构造方法保存advice信息AdvisedSupport 
			return new JdkDynamicAopProxy(config);
		}
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		return new JdkDynamicAopProxy(config);
	}
}

//已jdk代理为例
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
	Assert.notNull(config, "AdvisedSupport must not be null");
	if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
		throw new AopConfigException("No advisors and no TargetSource specified");
	}
	this.advised = config;
	//获取原始类的接口 JKD动态代理必须是有接口的
	this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
	findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
}

  • 接下来分析getProxy -> JdkDynamicAopProxy.getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
	}
	Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
	findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
	//很熟悉的创建代理方式 如果不理解先移步看动态代理
	return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

至此代理对象就创建好了,返回到IOC容器中的就是代理对象了。

3.运行阶段 -> 动态代理的反射调用

  • 调用某个方法是拿到的是代理对象,贴下JdkDynamicAopProxy代理类
//上面看到这个,执行回调方法为 this ,那么就说明代理对象调用会走当前类的invoke方法
Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

//接下来看invoker方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	Object oldProxy = null;
	boolean setProxyContext = false;
	//获取原始类封装SingletonTargetSource
	TargetSource targetSource = this.advised.targetSource;
	Object target = null;

	try {
		//一系列的判断删掉
		......

		//获取到原始类
		target = targetSource.getTarget();
		//类信息
		Class<?> targetClass = (target != null ? target.getClass() : null);

		//chain 链/管道的意思 获取拦截器管道
		//一直往下跟 实际上就是包装了一下 同时存了缓存 interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
		//interceptor 就是registry.getInterceptors(advisor);通过构造方法初始化前置 后置 异常
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
		if (chain.isEmpty()) {
			//管道为空
			Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
			//直接通过反射调用原始类
			retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
		}
		else {
			// We need to create a method invocation...
			MethodInvocation invocation =
					new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
			//开始调用管道 我们接下来走这里
			retVal = invocation.proceed();
		}

		//后面就是返回指定额处理了,先去掉
		。。。
	}
	finally {
		if (target != null && !targetSource.isStatic()) {
			// Must have come from TargetSource.
			targetSource.releaseTarget(target);
		}
		if (setProxyContext) {
			// Restore old proxy.
			AopContext.setCurrentProxy(oldProxy);
		}
	}
}
  • 接下来invocation.proceed() ->ReflectiveMethodInvocation.proceed()
//成员变量
//执行的管道调用链 上面通过构造方法赋值
protected final List<?> interceptorsAndDynamicMethodMatchers;
private int currentInterceptorIndex = -1;


//开始责任链调用
public Object proceed() throws Throwable {
    // We start with an index of -1 and increment early.
    //如果当前执行的下标等于执行的size-1 说明是到最后一个执行了 则执行原生调用方法
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        //这里面跟进去就是这个 return method.invoke(target, args);
        return invokeJoinpoint();
    }
	//下标+1 就是从0开始 默认值是-1
    Object interceptorOrInterceptionAdvice =
        this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    //如果要动态匹配joinPoint
    if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
        // Evaluate dynamic method matcher here: static part will already have
        // been evaluated and found to match.
        InterceptorAndDynamicMethodMatcher dm =
            (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
        Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
        //动态匹配:运行时参数是否满足匹配条件
        if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
            //主要看前置后置和异常 传入的参数是this 
            //例如前置切面执行完会再次调用到该方法
            return dm.interceptor.invoke(this);
        }
        else {
            //继续递归
            return proceed();
        }
    }
    else {
       	//如果不是 直接调用MethodInterceptor
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}
  • dm.interceptor.invoke(this) -> AspectJAfterAdvice.invoke 调用通知的方法,挑一个看吧
//调用之后 其他的可以自己了解
public Object invoke(MethodInvocation mi) throws Throwable {
	try {
		//反射调用原始类
		return mi.proceed();
	}
	finally {
		//调用返回后的切面方法
		invokeAdviceMethod(getJoinPointMatch(), null, null);
	}
}

总结

在容器初始化bean之后,回调到后置通知方法,aop正好实现后置通知方法,经过判断如果满足当前的配置切点则生成代理类并返回到IOC容器中。
创建代理类时会把原始类、调用链路等信息通过构造方法保存下来,在创建动态代理时newInstance时传入的回调handler类也是this,那么在调用该代理类时会到handler类的invoke方法
在invoke方法中通过递归以及增加下标的方法使调用链路执行反射调用,如果不能正常匹配到对应的Advice类,则在到最后一个时直接反射调用原始类并返回
如果能正常匹配到,例如上面的AspectJAfterAdvice则是先反射调用原始类,然后再调用后置切面方法,整个流程结束

至此整个AOP切面的源码就分析完了,看完这些代码,再手写一般简单的应没啥问题了吧!
下一节MVC源码篇,都是基于IOC容器来,思想和AOP差不多。

以上就是本章的全部内容了。

上一篇:Spring源码分析第二弹 - DI 依赖注入分析
下一篇:Spring源码分析第四弹 - MVC分析

莫等闲,白了少年头,空悲切