Spring源码剖析-拜托面试官别再问我AOP原理了

导读:本篇文章讲解 Spring源码剖析-拜托面试官别再问我AOP原理了,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

目录

前言

IOC/DI , AOP 是Spring最重要的两个特性 ,也是面试高频被问到的部分,前面我们已经分析了Spring的IOC相关源码以及DI依赖注入相关源码,从本篇文章开始我们着手分析Spring的AOP源码 。

开始之前,你需要对AOP 原理,JDK动态代理,CGLIB动态代理有一定的理解。这里先上一个图,后面源码分析的时候可以看着图来

在这里插入图片描述

AOP的理解

AOP基本概念

AOP是为面向切面编程,为什么要面向切面,何为切面?我们知道对于OOP面向对象而言在某些开发场景中是有一定不足,由于面向对象的思想是纵向的,它面对的是一个一个的对象,当我们需要在多个类中引入同一个公共的业务时(比如:事务,操作日志等),那么在每个类中都要引入公共的业务代码,从而造成代码大量重复,代码结构不优雅,不方便维护 ,这个时候就需要使用到面向切面的编程来解决这个问题。使用AOP可以把分散在多个类中的公共的代码剥离出来,和业务本身的代码解耦, 然后通过动态代理将公共业务代码作用到多个对象,代码结构也更加优雅。

所以可以认为 面向切面 是对 面向对象 的补充,它的思想是横向的,它面向的是一个切面,如果把一个对象看做一个点,那么多个对象就是一个面,是为切面,AOP多用于:事务,日志,监控,流控等等业务场景。
在这里插入图片描述

AOP实现原理

AOP的实现原理是基于动态代理,动态代理就是在运行时期动态的为某个类(原生类)生成代理类以达到代码增强的目的,且代理类是持有原生类的,可以在代理类中调用原生类以及做一些增强业务。

动态代理分为JDK动态代理和CGLIB代理,CGLIB代理需要导入相关的jar包。两者的区别是JDK动态代理要求原始类(被代理类)需要实现至少一个接口。而CGLIB则是基于继承进行代理,原生类可以不实现任何接口。

对于Spring而言默认采用JDK动态代理,如果原生类没有实现任何接口,Spring会选择CGLIB代理,或者你可以通过配置文件强制指定使用CGLIB代理。

AOP案例

下面我们使用AOP来做一个事务管理案例:在每个Service方法执行前后添加事务的代码

1.创建一个普通类,这个类的方法需要有事务

@Service
public class UserServiceImpl implements IUserService {

    public void insert() {
        System.out.println("UserServiceImpl.insert:保存User...");
    }

    public void delete() {
        System.out.println("UserServiceImpl.delete:删除User");
    }
}

2.创建一个切面类,这个类里面提供公共的业务代码,即:事务代码

@Component
@Aspect
public class TranscationManager {

    //定义切点,表达式作用于所有到service的所有的方法
    @Pointcut("execution(* cn.xxx.*.service.*.*(..))")
    public void pointcut(){}

    //前置通知 , 方法执行前执行,用来开启事务
    @Before("pointcut()")
    public void begin(JoinPoint joinPoint){

        System.out.println("TranscationManager.begin:开启事务...:");
    }
    //后置返回通知 ,方法正常返回后执行, 用来提交事务
    @AfterReturning("pointcut()")
    public void commit(){
        System.out.println("TranscationManager.commit:提交事物...");
    }

    //异常通知,方法出现异常调用,用来回滚事务
    @AfterThrowing(value = "pointcut()",throwing="e")
    public void rollback(JoinPoint joinPoint,Throwable e){
        System.out.println("TranscationManager.rollback:回滚事物咯...:"+e.getMessage());
    }

    //最终通知,不管方法会不会出现异常,都会执行,用来关闭资源
    @After("pointcut()")
    public void close(){
        System.out.println("TranscationManager.close:关闭连接...");
    }


    //环绕通知,拦截原始类的类的方法,可以通过 joinPoint调用原始的类
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint){
        

        return null;
    }

}

3.配置Spring支持AOP注解

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

    <!--开启IOC注解支持-->
    <context:component-scan base-package="cn.xx" />

    <!--开启AOP注解支持,默认使用jdk动态代理,如果指定 proxy-target-class=true 则实例CGLIB代理-->
    <aop:aspectj-autoproxy />

</beans>

4.测试代码

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:application_aop.xml")
public class AopTest {

    @Autowired
    private IUserService userService ;

    @Test
    public void testAop(){
        userService.insert();
        System.out.println("======================================");
        userService.delete();
    }
}

控制台效果

TranscationManager.begin:开启事务…:
UserServiceImpl.insert:保存User…
TranscationManager.commit:提交事物…
TranscationManager.close:关闭连接…
======================================
TranscationManager.begin:开启事务…:
UserServiceImpl.delete:删除User…
TranscationManager.commit:提交事物…
TranscationManager.close:关闭连接…

这里我们看到了,使用AOP可以把公共的代码剥离出去和业务变身代码解耦,同时也方便扩展。

怎么理解这个AOP案例,首先要明白需求:在多个service方法执行前,否 或 出现异常做出相应的事务处理。我们把UserService看着原生类, 把TranscationManager 切面看着是增强代码,那么Spring是如何做到把 TranscationManager 的增强逻辑 加入到 UserService的方法前后的呢?

  1. 找到所有原生类(被代理类):我们在 TranscationManager中定义了一个切点:@Pointcut("execution(* cn.xxx.*.service.*.*(..))") :这切点定义了一个表达式,这个表达式的含义就是找到cn.xxx包下所有的service的所有方法,Spring就知道了需要拦截这些方法的执行。

  2. 找到了service的方法,如何在方法前,后做事情?我们在TranscationManager中定义了@Before(“pointcut()”) 前置通知,@AfterReturning(“pointcut()”)后置通知等,当我们调用userService的方法之前就会触发 Before 前置通知中的逻辑 ,方法执行完成就会触发 AfterReturning 后置通知的逻辑,异常通知和最终通知也是一个道理。

  3. 实现原理就是动态代理,其实Spring为所有切点切到的类都生成了代理类,也就是说在test类中注入的 @Autowired private IUserService userService ; 其实并不是我们写的那个UserService,而是基于UserService代理出来的一个代理类。代理类持有原生类,且代理类和原生类有相同的方法,所以你感觉你在调用UserService,其实在调用代理类。

    在代理类中的方法对原生类方法做了增强 ,而增强的逻辑就是 TranscationManager 中的逻辑,比如调用userService.insert 实则进入了代理类的insert方法,方法中先调用TranscationManager@Before 前置通知业务,然后调用原生类的insert,方法结尾调用TranscationManager@AfterReturning 后置通知,出现异常调用TranscationManager@AfterThrowing异常通知等等。这样是不是就达到了上面的增强效果了。

如果没有去研究过JDK动态代理和CGLIB代理可能你看起来比较晕,对于Spring切面的东西这里不做太多解释了,不是本篇主要内容,下面我就对于这个AOP案例做源码分析。

AOP解析器

在上面的案例中我们通过 <aop:aspectj-autoproxy /> 配置来开启AOP支持,稍微动动脑袋能想到Spring一定会有一个类来处理该配置。 在Spring中有一个接口叫 NamespaceHandlerSupport ,它提供了Spring配置文件的namespace的解析支持。
在这里插入图片描述
其中有一个实现叫 AopNamespaceHandler , 它是针对于 <aop: 开头的namespace 解析支持,看一下这个类的源码

AOP解析器:AspectJAutoProxyBeanDefinitionParser

//aop命名空间的NamespaceHandler 。
//为<aop:config>标签提供一个BeanDefinitionParser 。 config标签可以包括嵌套的pointcut 、 advisor和aspect标签。
public class AopNamespaceHandler extends NamespaceHandlerSupport {

	/**
	 * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
	 * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
	 * and '{@code scoped-proxy}' tags.
	 */
	@Override
	public void init() {
		// In 2.0 XSD as well as in 2.5+ XSDs
		//<aop:config 解析器
		registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
		//【主角在这里】注册针对于<aop:aspectj-autoproxy 的解析器 AspectJAutoProxyBeanDefinitionParser
		registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
		registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

		// Only in 2.0 XSD: moved to context namespace in 2.5+
		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
	}

}

到这里我们看到了针对于 <aop:aspectj-autoproxy 的解析器 AspectJAutoProxyBeanDefinitionParser,它实现了BeanDefinitionParser,解析逻辑都在parse方法中,源码如下:

class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {

	//Element就是 <aop:aspectj-autoproxy 元素的封装
	@Override
	@Nullable
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		//注册一个 AspectJAnnotationAutoProxyCreator
		//用于处理当前应用程序上下文中的所有 AspectJ 切面,以及 Spring Advisor。
		AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
		//处理子节点
		extendBeanDefinition(element, parserContext);
		return null;
	}

	...省略...

}


该方法的作用主要是注册了一个 AspectJAnnotationAutoProxyCreator 自动代理创建器,它的作用就是用来处理Aop。 AspectJAutoProxyBeanDefinitionParser 的 parse 方法是在IOC启动过程中,通过DefaultBeanDefinitionDocumentReader#parseBeanDefinitions 委派 BeanDefinitionParserDelegate#parseCustomElement去解析的。

注册AnnotationAwareAspectJAutoProxyCreator

parse方法中比较重要的就是 AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary , 它创建了一个 AnnotationAwareAspectJAutoProxyCreator 代理自动创建器 ,AOP的功能重要就是通过它来完成的,它可以根据 Point 解定义的切点来自动代理相匹配的 bean,跟一下该方法源码:

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			ParserContext parserContext, Element sourceElement) {
		//【重要】通过BeanDefinitionRegistry注册一个 AnnotationAwareAspectJAutoProxyCreator
		BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
				parserContext.getRegistry(), parserContext.extractSource(sourceElement));
				
		//对 proxy-target-class 和 expose-proxy 属性处理
		useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
		//注册组件 把 beanDefinition 注册到ParserContext上下文中
		registerComponentIfNecessary(beanDefinition, parserContext);
	}

该方法做了三件事情

  • 通过BeanDefinitionRegistry注册一个 AnnotationAwareAspectJAutoProxyCreator ,该类是AspectJ 切面处理类
  • 对 proxy-target-class 和 expose-proxy 属性处理 ,就是把BeanDefinition中的proxyTargetClass和exposeProxy属性设置为true
  • 这次组件, 把AnnotationAwareAspectJAutoProxyCreator 的 beanDefinition 注册到ParserContext上下文中

我们继续跟踪注册AnnotationAwareAspectJAutoProxyCreator 的代码:AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary

	@Nullable
	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
			@Nullable Object source) {

		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
	}

	//BeanDefinitionRegistry:bean的注册器
	//cls:AnnotationAwareAspectJAutoProxyCreator的类型
	@Nullable
	private static BeanDefinition registerOrEscalateApcAsRequired(
			Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		//如果容器中已经包含了 org.springframework.aop.config.internalAutoProxyCreator 自动代理创建者的BeanDefinition
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			//获取BeanDefinition
			BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			//class比较
			if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
				//如果已经有自动创建器了,按照优先级比较选择使用哪一个
				int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
				int requiredPriority = findPriorityForClass(cls);
				if (currentPriority < requiredPriority) {
					apcDefinition.setBeanClassName(cls.getName());
				}
			}
			return null;
		}
		//如果容器中还没有注册自动创建器,就注册一个
		RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
		beanDefinition.setSource(source);
		beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
		beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		//通过BeanDefinitionRegistry注册一个 代理自动创建器
		registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
		return beanDefinition;
	}

方法会判断容器中如果已经注册了 自动代理创建器,则按照优先级选择使用哪个,如果么有注册就使用BeanDefinitionRegistry注册一个。

处理proxy-target-class和ExposeProxy

proxy-target-class 的对于 <aop:aspectj-autoproxy proxy-target-class=“true” /> 属性的处理,该属性的作用是指定代理的方式为CGLIB。

//对 proxy-target-class 和 expose-proxy 属性处理
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
	if (sourceElement != null) {
		//获取  <aop:aspectj-autoproxy proxy-target-class="" />  proxy-target-class 属性
		boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
		if (proxyTargetClass) {
			//如果proxyTargetClass=true,则使用CGLIB代理
			//definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
			//把 definition 中的 proxyTargetClass设置为true
			AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
		}
		//当exposeProxy为true时暴露代理对象,会把proxy动态代理对象设置到AopContext上下文中
		boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
		if (exposeProxy) {
			//definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
			//把 definition 中的 exposeProxy 设置为true
			AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
		}
	}
}

这里做了两个事情

  • 根据配置:<aop:aspectj-autoproxy proxy-target-class=“true” /> 将 definition 中的 proxyTargetClass设置为true ,生成代理将会使用CGLIB方式,否则默认使用JDK动态代理
  • 根据配置:<aop:aspectj-autoproxy proxy-target-class=“true” expose-proxy=“true” /> 将 definition 中的 exposeProxy设置为true ,目的是把创建的代理对象添加到AopContext上下文中,为什么要这麽做?如果有如下代码:
    public class AServiceImpl implements AService{
    	@Transactional
    	public void a(){
    		this.b();
    	}
    	@Transactional(propagation = Propagation.REQUIRES_NEW)
    	public void b(){
    	}
    }
    

    这里的 this 是原生类,并不是代理类,也就意味这b的 @Transactional(propagation = Propagation.REQUIRES_NEW)
    事务增强代码是不会执行的,对于这个问题我们可以做如下处理

  1. 修改配置:<aop:aspectj-autoproxy expose-proxy=“true” />
  2. this.b() 修改为:((AService)AopContext.currentProxy()).b(); 得到代理类执行b()方法

增强器

上面的一个大堆流程主要是创建了一个 AnnotationAwareAspectJAutoProxyCreator ,那么它是如何来处理AOP的呢?看一下它的继承体系
在这里插入图片描述
AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor,当Spring实例化这个Bean时会在这个Bean的initMethod初始化之后调用postProcessAfterInitialization方法,Aop的实现就在这里开始。AbstractAutoProxyCreator#postProcessAfterInitialization源码如下:


	 * Create a proxy with the configured interceptors if the bean is
	 * identified as one to proxy by the subclass.
	 * @see #getAdvicesAndAdvisorsForBean
	 */
	 //如果 bean 被子类标识为代理,则使用配置的拦截器创建一个代理。
	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
		if (bean != null) {
			//根据Bean的class和name,创建一个缓存的key  ,
			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) {
		//如果已经处理过,就直接返回Bean
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		//不需要增强
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		//是基础设施类(比如 Pointcut.class,Aspect.class等基础类不需要代理),
		// 或者是原始类不做代理,比如 beanName以 .ORIGINAL 结尾就会跳过代理
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		//获取增强,即:获取到上面案例中的TranscationManager中的增强方法,封装成一个一个,InstantiationModelAwarePointcutAdvisorImpl,该类可以是对切面方法的封装
		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));
			//把代理的type放入proxyTypes
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}
		//缓存的key放入advisedBeans
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

方法中先判断了Bean是否需要创建代理,比如当前bean是Aspect,pintcut等基础设施类就不需要代理,然后调用 getAdvicesAndAdvisorsForBean 获取到增强器 ,最后 调用createProxy方法创建代理对象。

获取增强器

获取增强器是在 AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean中完成的 ,我们来一步步跟踪一下它的获取流程


	//[第一步] 找到增强器
	@Override
	@Nullable
	protected Object[] getAdvicesAndAdvisorsForBean(
			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
		//找打增强器,提取成Advisor
		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}

	//[第二步]  找到所有增强器,以及找到bean适用的增强器
	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		//找到所有增强方法
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		//找到当前bean适用的增强方法
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

上面逻辑做了两件事情, 找到所有增强器,以及找到bean适用的增强器,查找所有增强器在 AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors中完成的,源码如下:

@Override
	protected List<Advisor> findCandidateAdvisors() {
		// Add all the Spring advisors found according to superclass rules.
		//调用父类,查找所有的增强方法
		List<Advisor> advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.
		if (this.aspectJAdvisorsBuilder != null) {
		//调用 aspectJAdvisorsBuilder.buildAspectJAdvisors 构建增强器
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}

这里主要通过 aspectJAdvisorsBuilder 去查找增强器,然后添加到advisors集合中返回。

public List<Advisor> buildAspectJAdvisors() {
		//得到切面类
		List<String> aspectNames = this.aspectBeanNames;

		if (aspectNames == null) {
			synchronized (this) {
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {
					List<Advisor> advisors = new LinkedList<>();
					aspectNames = new LinkedList<>();
					//获取到spring中所有的beanNames
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);
					for (String beanName : beanNames) {
						//循环BeanName 获取增强方法
						if (!isEligibleBean(beanName)) {
						//不合法的Bean跳过
							continue;
						}
						// We must be careful not to instantiate beans eagerly as in this case they
						// would be cached by the Spring container but would not have been weaved.
						//根据名字得到类型
						Class<?> beanType = this.beanFactory.getType(beanName);
						if (beanType == null) {
							continue;
						}
						//是否是切面类,有aspect注解,不是切面不做处理
						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);
								//查找增强方法,前置,后置,异常,最终通知
								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 {
								// Per target or per this.
								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<>();
		//找到所有切面类
		for (String aspectName : aspectNames) {
			//获取切面类的增强方法
			List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
			if (cachedAdvisors != null) {
				advisors.addAll(cachedAdvisors);
			}
			else {
				MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
				advisors.addAll(this.advisorFactory.getAdvisors(factory));
			}
		}
		//返回增强器
		return advisors;
	}

上面方法会先得到切面类 aspectNames,然后根据切面类从 advisorsCache缓存中得到增强方法并返回。

解析切面中的增强方法

当然如果还没有切面和增强方法,就会先从容器中得到所有的BeanName循环得到class,通过判断是否有aspect注解来得到切面。得到切面后,通过this.advisorFactory.getAdvisors(factory)提取切面中的增强方法,并缓存到advisorsCache map中。下面是 ReflectiveAspectJAdvisorFactory#getAdvisors 源码

@Override
	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
		//获取切面类
		Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		//获取切面名字
		String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
		//校验切面类
		validate(aspectClass);

		// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
		// so that it will only instantiate once.
		MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
				new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

		List<Advisor> advisors = new LinkedList<>();
		//使用反射工具, ReflectionUtils#doWithMethods 获取切面类的所有方法
		for (Method method : getAdvisorMethods(aspectClass)) {
			//提取增强方法 , 把 method 提出成 Advisor【重要】
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		// If it's a per target aspect, emit the dummy instantiating aspect.
		if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
			advisors.add(0, instantiationAdvisor);
		}

		// Find introduction fields.
		for (Field field : aspectClass.getDeclaredFields()) {
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		return advisors;
	}

上面业务中通过 getAdvisorMethods(aspectClass) 获取切面类所有的方法,底层通过ReflectionUtils#doWithMethods 反射实现。 然后调用 ReflectiveAspectJAdvisorFactory#getAdvisor 提取出切面中的增强器 Advisor(对增强方法的封装)。重点看一下 getAdvisor 源码

@Override
	@Nullable
	public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrderInAspect, String aspectName) {
		//验证
		validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
		//获取切点信息,其实就是获取注解表达式获取如:@Before("point()")
		AspectJExpressionPointcut expressionPointcut = getPointcut(
				candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
		if (expressionPointcut == null) {
			return null;
		}
		//根据切点信息生成增强器
		//把切面的增强方法提取成一个一个的  Advisor,
		//由Advisor的实现类InstantiationModelAwarePointcutAdvisorImpl 进行统一封装 
		return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
				this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
	}

==============================================================================================
		//获取切点信息,其实就是获取注解表达式获取如:@Before("point()")
	@Nullable
	private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
		//【第一步】找到方法上的注解
		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
			return null;
		}
		
		AspectJExpressionPointcut ajexp =
				new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
		//【第二步】得到注解表达式:如:pointcut()或者 @Pointcut(" execution(...)")
		//封装到AspectJExpressionPointcut对象
		ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
		if (this.beanFactory != null) {
			ajexp.setBeanFactory(this.beanFactory);
		}
		return ajexp;
	}
===============================================================================================

	//找到切面注解
	@SuppressWarnings("unchecked")
	@Nullable
	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
			AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
			if (foundAnnotation != null) {
				return foundAnnotation;
			}
		}
		return null;
	}

在上面逻辑中,把切面的增强方法提取成一个一个的 Advisor,由Advisor的实现类InstantiationModelAwarePointcutAdvisorImpl 进行统一封装 ,源码如下:

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
			Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
		//切入点
		this.declaredPointcut = declaredPointcut;
		//切面类的类型
		this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
		//增强的方法名
		this.methodName = aspectJAdviceMethod.getName();
		//方法的参数
		this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
		//
		this.aspectJAdviceMethod = aspectJAdviceMethod;
		this.aspectJAdvisorFactory = aspectJAdvisorFactory;
		this.aspectInstanceFactory = aspectInstanceFactory;
		this.declarationOrder = declarationOrder;
		this.aspectName = aspectName;

		if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			// Static part of the pointcut is a lazy type.
			Pointcut preInstantiationPointcut = Pointcuts.union(
					aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);

			// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
			// If it's not a dynamic pointcut, it may be optimized out
			// by the Spring AOP infrastructure after the first evaluation.
			this.pointcut = new PerTargetInstantiationModelPointcut(
					this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
			this.lazy = true;
		}
		else {
			// A singleton aspect.
			this.pointcut = this.declaredPointcut;
			this.lazy = false;
			//实例化 增强器
			this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
		}
	}

上面构造方法是把增强方法相关的信息进行了赋值,最后调用了一个 instantiateAdvice 来对增强器进行初始化,不同的增强逻辑不同,比如Before,After 他们的增强前置是不同的,所以需要不同的增强器来完成不同的逻辑,见:instantiateAdvice 方法源码

创建增强器

private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
		Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
				this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
		return (advice != null ? advice : EMPTY_ADVICE);
	}

@Override
	@Nullable
	public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
		//切面类
		Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		//验证
		validate(candidateAspectClass);
		//找到增强方法的注解封装
		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
			return null;
		}

		// If we get here, we know we have an AspectJ method.
		// Check that it's an AspectJ-annotated class
		//判断class是否是切面
		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;
		//不同的增强做出不同的处理,创建了不同的 Advice
		switch (aspectJAnnotation.getAnnotationType()) {
			case AtBefore:
			//前置AspectJMethodBeforeAdvice
				springAdvice = new AspectJMethodBeforeAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfter:
			//最终通知
				springAdvice = new AspectJAfterAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfterReturning:
				//后置通知
				springAdvice = new AspectJAfterReturningAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterReturningAnnotation.returning())) {
					springAdvice.setReturningName(afterReturningAnnotation.returning());
				}
				break;
			case AtAfterThrowing:
				//异常通知
				springAdvice = new AspectJAfterThrowingAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
					springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
				}
				break;
			case AtAround:
				//环绕通知
				springAdvice = new AspectJAroundAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtPointcut:
				//切点
				if (logger.isDebugEnabled()) {
					logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
				}
				return null;
			default:
				throw new UnsupportedOperationException(
						"Unsupported advice type on method: " + candidateAdviceMethod);
		}

		// Now to configure the advice...
		springAdvice.setAspectName(aspectName);
		springAdvice.setDeclarationOrder(declarationOrder);
		//给增强器设置参数
		String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
		if (argNames != null) {
			springAdvice.setArgumentNamesFromStringArray(argNames);
		}
		springAdvice.calculateArgumentBindings();

		return springAdvice;
	}

这里根据不同的增强注解生成不同的增强器,比如 AtBefore 会对应 AspectJMethodBeforeAdvice ,比如 AtAfter 对应了 AspectJAfterAdvice。增强器中都提供了一个 invoke 来调用增强方法。如AspectJMethodBeforeAdvice

public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {

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

		super(aspectJBeforeAdviceMethod, pointcut, aif);
	}


	@Override
	public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
		//调用增强方法,即调用@Before注解的前置通知方法
		invokeAdviceMethod(getJoinPointMatch(), null, null);
	}

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

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

}

增强器的调用

这里有个疑问,上面已经针对不同的注解生成了不同的增强器,那么这些增强器在什么时候调用呢?当然是在我们调用对象的方法的时候,触发前置,后置等增强。在Spring内部有一个 MethodBeforeAdviceInterceptor 拦截器,该拦截器会在创建Bean的代理的时候被创建,它的作用就是在方法调用前拦截,我们看一下源码:

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();
	}

}

对于后置增强没有Interceptor ,而是在拦截器链中直接调用 AspectJAfterAdvice

public class AspectJAfterAdvice extends AbstractAspectJAdvice
		implements MethodInterceptor, AfterAdvice, Serializable {

	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;
	}

}

其他的增强这里就不一一分析了 , 到这里我们基本上把增强器的解析流程分析完成了。

选择适用的增强器

在上面分析中已经找到了所有增强,但是不是所有增强器都适合,所以会过滤出适用的增强,主要实现在AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply,其实就是找到满足我们配置的 切入点 的增强器,具体的细节这里就进去分析了。

创建代理

上面流程走完,找到了适合当前Bean的增强器,然后就会为当前Bean创建代理了,通过AbstractAutoProxyCreator#createProxy 完成

代理创建器:AbstractAutoProxyCreator

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 proxyFactory = new ProxyFactory();
		//拷贝当前类的属性
		proxyFactory.copyFrom(this);
		//判断是基于接口的代理,就是判断 <aop:aspectj-autoproxy proxy-target-class="false" 属性
		//默认fasle,即:走JDK动态代理
		if (!proxyFactory.isProxyTargetClass()) {
			//确定给定的 bean 是否应该用它的目标类而不是它的接口来代理。
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				//找到被代理类的接口interface ,添加到到 proxyFactory 代理工厂中
				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);
		}
		//通过 ProxyFactory 创建代理
		return proxyFactory.getProxy(getProxyClassLoader());
	}

看得出这个方法在配置代理工厂,ProxyFactory,配置好之后通过代理工厂创建代理。方法做了如下事情

  • 把当前类中的属性添加到工厂
  • 把被代理的接口添加到工厂
  • 把增强器添加到工厂
  • 把要代理的原始类添加到工厂
  • 创建代理

该方法中通过判断 proxy-target-class=“false” 来决定采用JDK动态代理或者CGLIB代理,之前有分析过

  • 如果被代理类有接口,Spring默认使用JDK动态代理
  • 如果被代理类有接口,可以配置 proxy-target-class=“true” 强制使用CGLIB代理
  • 如果被代理类没有接口,只能选择CGLIB代理 ,因为JDK动态代理只是支持有有接口的类,CGLIB是为被代理类生成一个子类,复写其所有方法来达到增强,CGLIB代理需要引入CGLIB库

继续跟进 proxyFactory.getProxy 方法

public Object getProxy(@Nullable ClassLoader classLoader) {
		//先创建一个JDKDynamicAopProxy  , 然后创建代理类
		return createAopProxy().getProxy(classLoader);
	}


-----------------------------------------------------------------------------------------------

	@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.");
			}
			//判断目标是否有接口,选择使用JdkDynamicAopProxy创建代理,否则使用CGLIB
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			//使用ObjenesisCglibAopProxy创建代理
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

ProxyFactory#getProxy 首先会创建一个AopProxy 代理创建器,根据目标类是否有接口来选择使用JDK代理:JdkDynamicAopProxy 和CGLIB代理:ObjenesisCglibAopProxy。然后调用getProxy方法创建代理。

JDK动态代理:JDKDynamicAopProxy

JdkDynamicAopProxy 实现了 InvocationHandler,InvocationHandler是JDK动态代理最核心的一个类,代理对象的方法调用都会被委托到 invoke 方法中去执行,JdkDynamicAopProxy#getProxy 源码如下:

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {

	//创建代理
	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
		}
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		//创建代理类
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}


	//...省略代码...
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		//方法调用
		MethodInvocation invocation;
		Object oldProxy = null;
		boolean setProxyContext = false;
		
		TargetSource targetSource = this.advised.targetSource;
		Object target = null;

		try {
			// 如果是equals方法:目标类本身没有实现 equals(Object) 方法。
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				// The target does not implement the equals(Object) method itself.
				return equals(args[0]);
			}
			//如果是hashCode方法:目标类本身没有实现 hashCode() 方法。
			else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				// The target does not implement the hashCode() method itself.
				return hashCode();
			}
			else if (method.getDeclaringClass() == DecoratingProxy.class) {
				// There is only getDecoratedClass() declared -> dispatch to proxy config.
				return AopProxyUtils.ultimateTargetClass(this.advised);
			}
			//调用Advised 接口或者其父接口中定义的方法
			else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				// Service invocations on ProxyConfig with the proxy config...
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;
			
			if (this.advised.exposeProxy) {
				// Make invocation available if necessary.
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			// Get as late as possible to minimize the time we "own" the target,
			// in case it comes from a pool.
			//目标类
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			// Get the interception chain for this method.
			//获取此方法的拦截器通知链
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			// Check whether we have any advice. If we don't, we can fallback on direct
			// reflective invocation of the target, and avoid creating a MethodInvocation.
			if (chain.isEmpty()) {
			//如果没有拦截器能应用到该方法,直接反射调用方法
				// We can skip creating a MethodInvocation: just invoke the target directly
				// Note that the final invoker must be an InvokerInterceptor so we know it does
				// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				//创建 ReflectiveMethodInvocation 方法调用
				// We need to create a method invocation...
				invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// Proceed to the joinpoint through the interceptor chain.
				//通过拦截器链进入连接点
				retVal = invocation.proceed();
			}

			// Massage return value if necessary.
			Class<?> returnType = method.getReturnType();
			if (retVal != null && retVal == target &&
					returnType != Object.class && returnType.isInstance(proxy) &&
					!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
				// Special case: it returned "this" and the return type of the method
				// is type-compatible. Note that we can't help if the target sets
				// a reference to itself in another returned object.
				retVal = proxy;
			}
			else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
				throw new AopInvocationException(
						"Null return value from advice does not match primitive return type for: " + method);
			}
			return retVal;
		}
		finally {
			if (target != null && !targetSource.isStatic()) {
				// Must have come from TargetSource.
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				// Restore old proxy.
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}
}

invoke方法中首先获取方法的拦截器通知链,如果有就会创建 MethodInvocation来调用方法,应用通知,如果没有拦截器链就直接反射调用方法。

方法增强拦截器:advice的织入

拦截器通知链是通过getInterceptorsAndDynamicInterceptionAdvice得到的:

	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable 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;
	}
-----------------------------------------------
	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
			Advised config, Method method, @Nullable Class<?> targetClass) {

		// This is somewhat tricky... We have to process introductions first,
		// but we need to preserve order in the ultimate list.
		//用来装拦截器
		List<Object> interceptorList = new ArrayList<>(config.getAdvisors().length);
		Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
		boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
		//注册一系列 AdvisorAdapter,用于将 Advisor 转化成 MethodInterceptor
		AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

		for (Advisor advisor : config.getAdvisors()) {
			if (advisor instanceof PointcutAdvisor) {
				// Add it conditionally.
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
				//把advisor转换成MethodInterceptor
					MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
					//检查当前 advisor 的 pointcut 是否可以匹配当前方法
					MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
					if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
						if (mm.isRuntime()) {
							// Creating a new object instance in the getInterceptors() method
							// isn't a problem as we normally cache created chains.
							for (MethodInterceptor interceptor : interceptors) {
								//加到interceptorList
								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;
	}

getInterceptorsAndDynamicInterceptionAdvice这个方法主要是把Advisor 转成 MethodInterceptor , 也就是说Advisor可以应用到连接点,也就是当代理对象方法被调用时就可以触发相应的 Advisor 通知了。

在AOP中为各种通知封装了不同的拦截器,在上面代码中出现一个注册器:GlobalAdvisorAdapterRegistry 其中委托AdvisorAdapterRegistry 来实现增强拦截器的注册,默认实现类是DefaultAdvisorAdapterRegistry 代码如下:

public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {

	private final List<AdvisorAdapter> adapters = new ArrayList<>(3);


	/**
	 * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
	 * 创建一个注册器,用来注册各种适配器
	 */
	public DefaultAdvisorAdapterRegistry() {
		//方法前置通知适配器
		registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
		//后置通知适配器
		registerAdvisorAdapter(new AfterReturningAdviceAdapter());
		//异常通知适配器
		registerAdvisorAdapter(new ThrowsAdviceAdapter());
	}

	//把advice 通知 包裹成 Advisor 增强器
	@Override
	public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
		if (adviceObject instanceof Advisor) {
			return (Advisor) adviceObject;
		}
		if (!(adviceObject instanceof Advice)) {
			throw new UnknownAdviceTypeException(adviceObject);
		}
		Advice advice = (Advice) adviceObject;
		if (advice instanceof MethodInterceptor) {
			// So well-known it doesn't even need an adapter.
			return new DefaultPointcutAdvisor(advice);
		}
		for (AdvisorAdapter adapter : this.adapters) {
			// Check that it is supported.
			if (adapter.supportsAdvice(advice)) {
				return new DefaultPointcutAdvisor(advice);
			}
		}
		throw new UnknownAdviceTypeException(advice);
	}

	//获取增强的方法拦截器
	@Override
	public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
		List<MethodInterceptor> interceptors = new ArrayList<>(3);
		//通知
		Advice advice = advisor.getAdvice();
		if (advice instanceof MethodInterceptor) {
			interceptors.add((MethodInterceptor) advice);
		}
		for (AdvisorAdapter adapter : this.adapters) {
			
			if (adapter.supportsAdvice(advice)) {
				//通过适配器把advisor转发成MethodInterceptor
				interceptors.add(adapter.getInterceptor(advisor));
			}
		}
		if (interceptors.isEmpty()) {
			throw new UnknownAdviceTypeException(advisor.getAdvice());
		}
		return interceptors.toArray(new MethodInterceptor[0]);
	}

	//注册适配器
	@Override
	public void registerAdvisorAdapter(AdvisorAdapter adapter) {
		this.adapters.add(adapter);
	}

}

下面是 MethodBeforeAdviceAdapter的源码:

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

	@Override
	public boolean supportsAdvice(Advice advice) {
		//是否支持
		return (advice instanceof MethodBeforeAdvice);
	}

	@Override
	public MethodInterceptor getInterceptor(Advisor advisor) {
		MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
		//给定一个MethodBeforeAdvice 前置通知  ,返回一个MethodBeforeAdviceInterceptor 方法前置拦截
		return new MethodBeforeAdviceInterceptor(advice);
	}

}

MethodBeforeAdviceInterceptor 是针对于前置通知的拦截器,在拦截方法的执行之前,可用触发前置通知,源码如下:

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();
	}

}

下面是 AfterReturningAdviceAdapter 后置通知适配器源码:

class AfterReturningAdviceAdapter implements AdvisorAdapter, Serializable {

	@Override
	public boolean supportsAdvice(Advice advice) {
		return (advice instanceof AfterReturningAdvice);
	}

	@Override
	public MethodInterceptor getInterceptor(Advisor advisor) {
		AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice();
		return new AfterReturningAdviceInterceptor(advice);
	}

}

下面是 AfterReturningAdviceInterceptor后置通知拦截器

public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {

	private final AfterReturningAdvice advice;


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

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		//先调用目标方法
		Object retVal = mi.proceed();
		//再调用后置增强
		this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
		return retVal;
	}

}

下面是ThrowsAdviceInterceptor 异常通知拦截器:

public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {

	private static final String AFTER_THROWING = "afterThrowing";

	private static final Log logger = LogFactory.getLog(ThrowsAdviceInterceptor.class);


	private final Object throwsAdvice;
	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			//执行目标方法
			return mi.proceed();
		}
		catch (Throwable ex) {
			//收集异常,获取异常增强方法
			Method handlerMethod = getExceptionHandler(ex);
			if (handlerMethod != null) {
				//调用异常增强
				invokeHandlerMethod(mi, ex, handlerMethod);
			}
			throw ex;
		}
	}

	private void invokeHandlerMethod(MethodInvocation mi, Throwable ex, Method method) throws Throwable {
		Object[] handlerArgs;
		if (method.getParameterCount() == 1) {
			handlerArgs = new Object[] { ex };
		}
		else {
			handlerArgs = new Object[] {mi.getMethod(), mi.getArguments(), mi.getThis(), ex};
		}
		try {
			//调用异常增强
			method.invoke(this.throwsAdvice, handlerArgs);
		}
		catch (InvocationTargetException targetEx) {
			throw targetEx.getTargetException();
		}
	}

使用反射调用方法

上面分析了Advice通知的注入过程,以及前置,后置,异常通知拦截器代码分析,现在代码回到 JdkDynamicAopProxy #invoke方法中 , 得到方法的拦截器后,如果方法没有拦截器通知链,就直接反射调用方法,否则会创建 ReflectiveMethodInvocation来调用方法

//获取此方法的拦截器通知链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
//如果没有拦截器能应用到该方法,直接反射调用方法
	// We can skip creating a MethodInvocation: just invoke the target directly
	// Note that the final invoker must be an InvokerInterceptor so we know it does
	// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
	Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
	retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
	//创建 ReflectiveMethodInvocation 方法调用
	// We need to create a method invocation...
	invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
	// Proceed to the joinpoint through the interceptor chain.
	//通过拦截器链进入连接点
	retVal = invocation.proceed();
}

AopUtils.invokeJoinpointUsingReflection 源码如下:

@Nullable
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
		throws Throwable {

	// Use reflection to invoke the method.
	try {
		//反射调用方法
		ReflectionUtils.makeAccessible(method);
		return method.invoke(target, args);
	}
	catch (InvocationTargetException ex) {
		// Invoked method threw a checked exception.
		// We must rethrow it. The client won't see the interceptor.
		throw ex.getTargetException();
	}
	catch (IllegalArgumentException ex) {
		throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
				method + "] on target [" + target + "]", ex);
	}
	catch (IllegalAccessException ex) {
		throw new AopInvocationException("Could not access method [" + method + "]", ex);
	}
}

通过 ReflectiveMethodInvocation 调用方法

@Override
@Nullable
public Object proceed() throws Throwable {
	//	We start with an index of -1 and increment early.
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		return invokeJoinpoint();
	}
	//拦截器
	Object interceptorOrInterceptionAdvice =
			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
	if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
		// Evaluate dynamic method matcher here: static part will already have
		// been evaluated and found to match.
		//动态匹配参数,看拦截器是否可用执行
		InterceptorAndDynamicMethodMatcher dm =
				(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
		if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
			return dm.interceptor.invoke(this);
		}
		else {
			// Dynamic matching failed.
			// Skip this interceptor and invoke the next in the chain.
			//匹配失败,跳过当前拦截器,执行下一个拦截器
			return proceed();
		}
	}
	else {
		// It's an interceptor, so we just invoke it: The pointcut will have
		// been evaluated statically before this object was constructed.
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}

总结

到这里AOP的源码分析就结束了,最后总结一下大致流程

  1. AopNamespaceHandler中注册了一个AOP解析器 AspectJAutoProxyBeanDefinitionParser
  2. AspectJAutoProxyBeanDefinitionParser创建了 代理自动创建器AnnotationAwareAspectJAutoProxyCreator
  3. AnnotationAwareAspectJAutoProxyCreator 负责解析AOP,和创建代理类
  4. AnnotationAwareAspectJAutoProxyCreator解析切面,找到所有的增强方法封装成增强器,并找到适合Bean的增强器
  5. 调用AbstractAutoProxyCreator创建代理,默认使用 JDKDynamicAopProxy JDK动态代理,如果 proxy-target-class=“true” 使用CglibAopProxy创建CGLIB代理。
  6. 对于前置,后置,异常等等通知都有对应的拦截器,当代理类被调用就会先走方法的拦截器进行增强逻辑的处理。

文章接收,喜欢就一键三连吧,你的肯定是我最大的动力。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/10645.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!