IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring源码系列: AOP实现 -> 正文阅读

[Java知识库]Spring源码系列: AOP实现

前言

AOP是什么,在我看来,先别提切面、织入这些概念性的东西。用通俗一点的话来说就是:在某个方法的前后,动态地插入我们自己的逻辑。当然,AOP的相关概念还是非常多的,在了解AOP之前,我们先来看下它有什么作用。

一. AOP的使用

这次的案例,我也不准备在Spring源码项目上建立了,直接自己新建了个项目,结构如下:
在这里插入图片描述
1.pom依赖:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>5.3.3</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.3</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.2.9.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.3.16</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13</version>
    <scope>test</scope>
</dependency>

2.用于拦截的Bean

public class TestBean {
	private String testStr = "Hello";

	public String getTestStr() {
		return testStr;
	}

	public void setTestStr(String testStr) {
		this.testStr = testStr;
	}

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

3.创建AspectJTest类:

@Aspect
public class AspectJTest {
	@Pointcut("execution(* *.test(..))")
	public void test() {

	}

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

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

	@Around("test()")
	public Object arountTest(ProceedingJoinPoint p) {
		System.out.println("AroundBefore");
		Object o = null;
		try {
			o = p.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("AroundAfter");
		return o;
	}
}

4.Test类:

public class Test {
	@org.junit.Test
	public void test(){
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("test/test.xml");
		TestBean bean = (TestBean) context.getBean("testBean");
		bean.test();
	}
}

5.test.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:aop="http://www.springframework.org/schema/aop"
	   xsi:schemaLocation="
   	http://www.springframework.org/schema/beans
   	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   	http://www.springframework.org/schema/aop
   	http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
	<aop:aspectj-autoproxy/>

	<bean name="testBean" class="com.TestBean"/>

	<bean class="com.AspectJTest"/>
</beans>

运行结果如下:
在这里插入图片描述

上述代码主要做了这么几件事:

  • 在所有类的test方法执行前后分别打印BeforeTestAfterTest信息。
  • 在所有类的方法执行前后又以环绕的方式,打印了AroundBeforeAroundAfter信息。

从代码上我们可以知道,我们使用了@Aspect注解,同时XML配置文件中又有这段配置声明:

<aop:aspectj-autoproxy/>

之后,我们来看下AOP是如何实现的。

二. AOP的实现

我们来看下AOP的调用入口AopNamespaceHandler

public class AopNamespaceHandler extends NamespaceHandlerSupport {
	@Override
	public void init() {
		registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
		// 这里就对应着我们XML的配置
		registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
		registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
	}

}

此时可以看到,在Spring解析配置文件的时候,遇到aspectj-autoproxy注解,就会使用解析器AspectJAutoProxyBeanDefinitionParser进行解析。

2.1 创建AnnotationAwareAspectJAutoProxyCreator

首先,Spring的解析器都是接口BeanDefinitionParser的实现,而该接口中只定义了一个方法parse(),因此其也是我们研究的入口函数,我们来看下AspectJAutoProxyBeanDefinitionParser.parse()方法:

class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
	@Override
	@Nullable
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		// 1.注册 AnnotationAwareAspectJAutoProxyCreator
		AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
		// 2.对于注解中子类的处理
		extendBeanDefinition(element, parserContext);
		return null;
	}
}

我们来看下第一步中对于AnnotationAwareAspectJAutoProxyCreator的注册步骤:

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
		ParserContext parserContext, Element sourceElement) {
	// 1.注册/升级 AnnotationAwareAspectJAutoProxyCreator
	BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			parserContext.getRegistry(), parserContext.extractSource(sourceElement));
	// 2.处理 proxy-target-class 以及 expose-proxy 属性
	useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
	// 3.注册组件并通知
	registerComponentIfNecessary(beanDefinition, parserContext);
}

紧接着,对这三点进行分别讲解:

2.1.1 注册或升级AnnotationAwareAspectJAutoProxyCreator

首先呢,我们先来说下AnnotationAwareAspectJAutoProxyCreator是干啥用的,它可以根据@Point注解定义的切点来自动代理相匹配的bean 也因此AOP的实现,基本上都是靠它来完成的。

咱们正常开发过程中,以AOP的使用为例。无非使用方式有两种:

  • XML配置。
  • 注解配置。

那本文主要围绕着XML配置来进行,从配置到现在,我们知道AOP的实现离不开AnnotationAwareAspectJAutoProxyCreator类。那好,这里我让大家看看,注解方式的配置和AnnotationAwareAspectJAutoProxyCreator又咋联系起来的。

首先,我们注解往往使用@EnableAspectJAutoProxy来标识AOP功能的启用,我们来看下该注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

}

这里通过@Import注解导入了AspectJAutoProxyRegistrar类,

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		// 注册或升级AnnotationAwareAspectJAutoProxyCreator
		// 调用的registerAspectJAnnotationAutoProxyCreatorIfNecessary方法是XML方式注册的方法的一个重载方法。
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
		// ...省略
	}
}

可见无论是XML配置还是注解配置,都离不开AnnotationAwareAspectJAutoProxyCreator类的帮助,好了,言归正传,我们来看下具体的注册或者升级流程做了什么事情:

public abstract class AopConfigUtils {
	@Nullable
	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {
		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
	}
	↓↓↓↓↓↓
	@Nullable
	private static BeanDefinition registerOrEscalateApcAsRequired(
			Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		// 1.若已经存在了 自动代理创建器
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			// 2.并且已存在的与当前的不一致,那么需要根据优先级来判断该使用哪个
			if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
				int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
				int requiredPriority = findPriorityForClass(cls);
				if (currentPriority < requiredPriority) {
					// 3.改变bean最重要的也就是改变其对应的className属性
					apcDefinition.setBeanClassName(cls.getName());
				}
			}
			// 4.若已经存在 自动代理创建器 并且和将要创建的一致,那么无需再次创建
			return null;
		}
		// 这里的cls指的是AnnotationAwareAspectJAutoProxyCreator.Class
		RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
		beanDefinition.setSource(source);
		beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
		beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		// 5.若不存在,那么此时注册一个 internalAutoProxyCreator 类型的 自动代理创建器
		registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
		return beanDefinition;
	}
}

这段代码的作用其实也就是对AnnotationAwareAspectJAutoProxyCreator类的一个注册,对于其作用将在后文展开。接下来看下第二步。

2.1.2 处理 proxy-target-class 以及 expose-proxy 属性

入口函数如下:

useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
↓↓↓↓↓
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
	if (sourceElement != null) {
		boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
		// 如果是proxy-target-class属性,且设置为true
		if (proxyTargetClass) {
			// 那么此时给对应的BeanDefinition添加的proxyTargetClass属性设置为true,以后创建代理的时候强制使用Cglib代理
			AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
		}
		boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
		// 如果是expose-proxy属性,并且为true。那么以后创建拦截器的时候会根据该属性来选择:是否暴露代理类
		if (exposeProxy) {
			AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
		}
	}
}

注意:

  • 若被代理的对象实现了至少一个接口,那么会使用JDK动态代理。同时所有该目标实现的接口都会被代理。
  • 若该对象没有实现任何接口,那么创建一个Cglib代理。

开启Cglib代理的方式如下:

<aop:aspectj-autoproxy proxy-target-class="true"/>

那么两者有啥区别呢?

  • JDK动态代理其代理对象必须是某个接口的实现,它通过在运行期间创建一个接口的实现类来完成对目标对象的代理。
  • Cglib代理在运行期间生成的代理对象为针对目标类扩展的子类。底层通过ASM操作字节码来实现,性能比JDK代理强。

注册组件通知就不再赘述了。

2.2 AnnotationAwareAspectJAutoProxyCreator的作用

我们先来看下该类的类关系图:
在这里插入图片描述
咱别的不说,就光看上图中红色框圈起来的地方,看来,AnnotationAwareAspectJAutoProxyCreator类实现了BeanPostProcessor接口。也因此,在Spring加载完这个Bean后,会调用postProcessAfterInitialization方法,根据类图关系,我们定位到AbstractAutoProxyCreator类中:

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			// 1.根据指定的beanClass和beanName,构建出一个key,格式:beanClassName_beanName
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				// 若它适合被代理,那么就封装指定的bean
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}
	↓↓↓↓↓
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		// 1.若已经被处理过,直接返回
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		// 2.无需增强
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		// 3.若当前bean为基础设施类 或者 配置指定了该bean不需要被自动代理,那么直接返回
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// 4.获取切面,若存在增强方法则创建代理
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			// 5.创建代理
			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;
	}
}

可见:

  1. 起因:AnnotationAwareAspectJAutoProxyCreator由于实现了BeanPostProcessor接口无疑会调用postProcessAfterInitialization()方法。
  2. 后果:该方法主要负责创建代理对象。经过一系列判断。开始创建代理。

2.3 获取增强器

而上述代码中比较重要的则是第四第五步。我们先来看下第四步,关于增强器(切面)的获取:

Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
↓↓↓↓↓
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
	@Override
	@Nullable
	protected Object[] getAdvicesAndAdvisorsForBean(
			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
		// 1.获取所有可用的切面
		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}
	↓↓↓↓↓
	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		// 1.获取所有的增强器
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		// 2.找到所有适用于当前bean的增强器,即作用域是否包括当前bean
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}
}

2.3.1 获取增强器findCandidateAdvisors

这里我们来看下Spring是如何获取增强器的,从代码出发:

List<Advisor> candidateAdvisors = findCandidateAdvisors();
↓↓↓↓↓↓这里调用的是子类实现,然后再用子类去调用父类↓↓↓↓↓↓
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
	@Override
	protected List<Advisor> findCandidateAdvisors() {
		// 1.这里调用父类方法,加载配置文件中的AOP声明,因为AOP的声明可能是注解,也可能是配置文件
		List<Advisor> advisors = super.findCandidateAdvisors();
		if (this.aspectJAdvisorsBuilder != null) {
			// 2.将符合条件的增强器加入到结果中
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}
}

我们先来看下第一步findCandidateAdvisors

public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
	protected List<Advisor> findCandidateAdvisors() {
		Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
		return this.advisorRetrievalHelper.findAdvisorBeans();
	}
}
↓↓↓↓↓
public class BeanFactoryAdvisorRetrievalHelper {
	public List<Advisor> findAdvisorBeans() {
		// 1.先看缓存中是否存在
		String[] advisorNames = this.cachedAdvisorBeanNames;
		if (advisorNames == null) {
			// 2.若缓存中不存在,从Spring容器中获取
			advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
					this.beanFactory, Advisor.class, true, false);
			this.cachedAdvisorBeanNames = advisorNames;
		}
		if (advisorNames.length == 0) {
			return new ArrayList<>();
		}

		List<Advisor> advisors = new ArrayList<>();
		// 3.遍历beanName找到对应的增强
		for (String name : advisorNames) {
			// 4.只有合法的bean才会去处理,默认默认返回的true
			if (isEligibleBean(name)) {
				if (this.beanFactory.isCurrentlyInCreation(name)) {
					if (logger.isTraceEnabled()) {
						logger.trace("Skipping currently created advisor '" + name + "'");
					}
				}
				else {
					try {
						// 进行注册返回
						advisors.add(this.beanFactory.getBean(name, Advisor.class));
					}
					catch (BeanCreationException ex) {
						// ...一大堆catch处理
					}
				}
			}
		}
		return advisors;
	}
}

再看下第二步buildAspectJAdvisors

public List<Advisor> buildAspectJAdvisors() {
	List<String> aspectNames = this.aspectBeanNames;

	if (aspectNames == null) {
		synchronized (this) {
			aspectNames = this.aspectBeanNames;
			if (aspectNames == null) {
				List<Advisor> advisors = new ArrayList<>();
				aspectNames = new ArrayList<>();
				// 1.从spring容器中获取所有的beanName
				String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
						this.beanFactory, Object.class, true, false);
				for (String beanName : beanNames) {
					// 2.不合法的bean直接略过
					if (!isEligibleBean(beanName)) {
						continue;
					}
					// 3.获取对应的bean类型
					Class<?> beanType = this.beanFactory.getType(beanName, false);
					if (beanType == null) {
						continue;
					}
					// 4.判断类上是否有@Aspect注解
					if (this.advisorFactory.isAspect(beanType)) {
						aspectNames.add(beanName);
						AspectMetadata amd = new AspectMetadata(beanType, beanName);
						if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
							// 5.//创建获取有@Aspect注解类的实例工厂,负责获取有@Aspect注解类的实例
							MetadataAwareAspectInstanceFactory factory =
									new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
							// 6.获得标记了AspectJ注解的增强方法。即获得切面对象
							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();
	}
	// 7.记录到缓存中
	List<Advisor> advisors = new ArrayList<>();
	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;
}

上述代码可以总结如下:

  1. 获取所有的beanName
  2. 遍历beanName,找出声明了AspectJ注解的类。
  3. 对标记了AspectJ注解的类进行切面的提取。
  4. 将提取结果加入到缓存中。

那么步骤三也是最为核心的,对应的代码为:

List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);

我们来探索下这个方法的具体实现:

public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
	@Override
	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
		// 1.获取标记位AspectJ的类
		Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		// 2.获取标记位AspectJ的name
		String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
		// 3.校验
		validate(aspectClass);
		// 4.包装工厂,保证其只会被实例化一次
		MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
				new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

		List<Advisor> advisors = new ArrayList<>();
		for (Method method : getAdvisorMethods(aspectClass)) {
			// 5.具体的切面获取操作,即普通切面的获取
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}
		// 6.若寻找的切面不是空,并且配置了 增强延迟初始化,那么需要在首位加入一个 同步实例化增强器
		if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
			advisors.add(0, instantiationAdvisor);
		}

		// 7.获取DeclareParents注解,主要用于引介增强的注解形式的实现。
		for (Field field : aspectClass.getDeclaredFields()) {
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}
		return advisors;
	}
}

我们先来重点看下第五步。

(1) 普通增强器的获取

我们来关注下这行代码:

Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);

@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
		int declarationOrderInAspect, String aspectName) {
	// 1.先进行校验
	validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
	// 2.获取切点信息
	AspectJExpressionPointcut expressionPointcut = getPointcut(
			candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
	if (expressionPointcut == null) {
		return null;
	}
	// 3.根据切点信息生成增强器
	return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
			this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

再来看下getPointcut函数做了什么事:

@Nullable
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
	// 1.获取方法上的注解
	AspectJAnnotation<?> aspectJAnnotation =
			AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
	if (aspectJAnnotation == null) {
		return null;
	}
	// 2.使用 AspectJExpressionPointcut 类来封装信息
	AspectJExpressionPointcut ajexp =
			new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
	// 3.提取注解中的表达式。例如本文案例中 @Pointcut("execution(* *.test(..))")
	ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
	if (this.beanFactory != null) {
		ajexp.setBeanFactory(this.beanFactory);
	}
	return ajexp;
}

我们继续探究第一步中findAspectJAnnotationOnMethod方法的调用流程:

@Nullable
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
	// 设置敏感的注解类,这里有:Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
	for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
		AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
		if (foundAnnotation != null) {
			return foundAnnotation;
		}
	}
	return null;
}

// 获取制定方法上的注解并使用AspectJAnnotation类来分装
@Nullable
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<>(result);
	}
	else {
		return null;
	}
}

到这里,获取切点信息的流程已经讲完,来看下第三步:根据切点信息生成增强器。Spring中,所有的增强都由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);
			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函数:

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);
}
↓↓↓↓getAdvice↓↓↓↓

public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
	@Override
	@Nullable
	public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
		// .. 省略
		switch (aspectJAnnotation.getAnnotationType()) {
			case AtPointcut:
				if (logger.isDebugEnabled()) {
					logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
				}
				return null;
			case AtAround:
				springAdvice = new AspectJAroundAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtBefore:
				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;
			default:
				throw new UnsupportedOperationException(
						"Unsupported advice type on method: " + candidateAdviceMethod);
		}
		// .. 省略
		return springAdvice;
	}
}

可以看到,Spring根据不同的注解生成对应的增强器。例如AtBefore则对应AspectJMethodBeforeAdvice。我们以此为例来分析下该类的实现。

(2) 总结☆

1.调用findCandidateAdvisors()方法获取所有的候选Class对象。

  • 这里先调用子类AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors()方法。
  • 子类显式地调用了父类AbstractAdvisorAutoProxyCreator.findCandidateAdvisors()方法用于加载那行可能通过XML配置加载的类。
  • 只有类上拥有@Aspect注解的,才会去寻找增强方法。

2.调用getAdvisors()方法,获取切面。

  • 普通切面的获取(看第三点)。
  • 若配置了增强延迟初始化,那么需要在首位加入一个 同步实例化增强器。
  • 获取DeclareParents注解。

3.循环遍历getAdvisor()进行切面的获取。

  • 校验
  • 调用getPointCut()方法找到这个 Advisor 里的切点 。
  • 根据切点信息生成增强器。

4.getPointCut()方法做了什么事?

  • 利用AspectJAnnotation类将获取到的方法上的注解进行封装,支持的注解有:Pointcut, Around, Before, After, AfterReturning, AfterThrowing
  • 再利用AspectJExpressionPointcut对象,将AspectJAnnotation实例封装起来,同时包含了PointCut的表达式。例如@Pointcut("execution(* *.test(..))")

5.根据切点信息生成增强器,增强器都由InstantiationModelAwarePointCutAdvisorImpl来封装。

  • 会根据第四步中获取到的具体注解,来生成对应的增强器进行处理。
  • 例如@Before则对应AspectJMethodBeforeAdvice

那么到这里为止,Spring已经完成了所有增强器的解析。即以下问题都在该步骤解决:

  1. Spring容器中哪些bean@AspectJ注解?
  2. 而这些bean又有哪些具体的增强?是@Around、@Before、@After的哪一个?

2.3.2 寻找匹配的增强器findAdvisorsThatCanApply

那么接下来就就是需要进行筛选,挑出适合当前bean的增强器,我们来看下findAdvisorsThatCanApply方法:

protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
	ProxyCreationContext.setCurrentProxiedBeanName(beanName);
	try {
		// 过滤操作
		return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
	}
	finally {
		ProxyCreationContext.setCurrentProxiedBeanName(null);
	}
}
↓↓↓↓↓↓
public abstract class AopUtils {
	public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		List<Advisor> eligibleAdvisors = new ArrayList<>();
		// 1.首先处理引介增强,调用canApply方法判断当前的bean和当前的advisor是否匹配
		for (Advisor candidate : candidateAdvisors) {
			if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
				eligibleAdvisors.add(candidate);
			}
		}
		boolean hasIntroductions = !eligibleAdvisors.isEmpty();
		for (Advisor candidate : candidateAdvisors) {
			// 引介增强已经在第一步被处理过
			if (candidate instanceof IntroductionAdvisor) {
				continue;
			}
			// 2.如果不是引介增强,则执行canApply方法判断是否匹配
			if (canApply(candidate, clazz, hasIntroductions)) {
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
	}
}

这里先来讲一下,什么是引介增强

引介增强是一种特殊的增强,其它的增强是方法级别的增强,即只能在方法前或方法后添加增强。而引介增强则不是添加到方法上的增强, 而是添加到类方法级别的增强,即可以为目标类动态实现某个接口,或者动态添加某些方法。

再看下代码,我们可以发现,无论是特殊的引介增强还是普通的增强,都会调用canApply函数来匹配bean和增强之间的关系。我们来看下该函数:

public static boolean canApply(Advisor advisor, Class<?> targetClass) {
	return canApply(advisor, targetClass, false);
}
↓↓↓↓↓↓
/**
 * @param advisor:增强对象
 * @param targetClass:目标类
 * @param hasIntroductions:是否含有引介增强
 * @return
 */
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
	// 1.如果是引介增强,则调用IntroductionAdvisor的getClassFilter.matches方法判断是否匹配
	if (advisor instanceof IntroductionAdvisor) {
		return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
	} else if (advisor instanceof PointcutAdvisor) {
		// 2.如果是普通增强,调用canApply方法判断是否匹配
		PointcutAdvisor pca = (PointcutAdvisor) advisor;
		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");
	// 看该类是否在pointcut的匹配范围内
	if (!pc.getClassFilter().matches(targetClass)) {
		return false;
	}
	// 是的话,再看是否能匹配此类的任意方法(引介增强),是的话则返回true
	MethodMatcher methodMatcher = pc.getMethodMatcher();
	if (methodMatcher == MethodMatcher.TRUE) {
		return true;
	}

	IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
	if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
		introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
	}
	// 存放要代理的类以及其接口
	Set<Class<?>> classes = new LinkedHashSet<>();
	// 不是JDK的代理类
	if (!Proxy.isProxyClass(targetClass)) {
		// 添加对应的实现类
		classes.add(ClassUtils.getUserClass(targetClass));
	}
	// 获取所有接口,包括父类
	classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
	for (Class<?> clazz : classes) {
		// 通过反射获取目标类的所有方法,进行逐一检测
		Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
		// 获取所有方法(包括父类),任意一个匹配即返回true
		for (Method method : methods) {
			if (introductionAwareMethodMatcher != null ?
					introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
					methodMatcher.matches(method, targetClass)) {
				return true;
			}
		}
	}

	return false;
}

总结下,就是:

  1. 首先查看定的类是否在Pointcut的匹配范围内。
  2. 是的话,再查看是否能匹配此类任意方法,是的话返回true
  3. 不能匹配任意方法,便会用反射的方法获取目标类的全部方法进行逐一检测。

2.4 创建代理

上面花了大篇幅所述的内容主要围绕着获取切面的步骤来展开的,那么接下来也就是AOP的最后一步:创建代理了,我们来回顾下外层的调用:

// 4.获取切面,若存在增强方法则创建代理
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
	this.advisedBeans.put(cacheKey, Boolean.TRUE);
	// 5.创建代理
	Object proxy = createProxy(
			bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
	this.proxyTypes.put(cacheKey, proxy.getClass());
	return proxy;
}

紧接着,我们围绕着createProxy方法来看下Spring做了什么事:

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
	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);
		}
		// 1.创建代理工厂类,并且复制当前类的属性
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);
		// 2.校验:给定的bean使用目标类还是其接口代理
		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				// 添加代理接口
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
		// 3.设置代理工厂的相关属性,将增强数组和目标对象加入其中
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);
		// 4.用来控制代理工厂被配置之后,是否允许修改通知
		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		ClassLoader classLoader = getProxyClassLoader();
		if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
			classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
		}
		// 5.主要还是委托ProxyFactory去创建代理类。
		return proxyFactory.getProxy(classLoader);
	}
}

这段代码的主要逻辑也就是:

  1. 创建代理工厂类,并且复制当前类的属性。
  2. 封装Advisor到工厂中。
  3. 设置要代理的类。
  4. 创建代理类。

其中我们来关注下第二步中涉及到的代码。

Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);

Spring中涉及到许多的拦截器、增强器、增强方法,通过它们来达到对逻辑的增强。因此此时传入的specificInterceptors对象,可能是上述的任意一种,那么buildAdvisors函数有必要将其统一进行封装,转化为Advisor来进行代理的创建。我们来看下其源码:

protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
	Advisor[] commonInterceptors = resolveInterceptorNames();

	List<Object> allInterceptors = new ArrayList<>();
	if (specificInterceptors != null) {
		// 1.加入拦截器
		if (specificInterceptors.length > 0) {
			allInterceptors.addAll(Arrays.asList(specificInterceptors));
		}
		// ...省略
	}
	// ...省略
	Advisor[] advisors = new Advisor[allInterceptors.size()];
	for (int i = 0; i < allInterceptors.size(); i++) {
		// 2.将拦截器封装为Advisor
		advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
	}
	return advisors;
}
↓↓↓↓wrap↓↓↓↓
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
	@Override
	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);
		}
		// 如果是 MethodInterceptor ,则使用DefaultPointcutAdvisor封装
		Advice advice = (Advice) adviceObject;
		if (advice instanceof MethodInterceptor) {
			// So well-known it doesn't even need an adapter.
			return new DefaultPointcutAdvisor(advice);
		}
		// 如果存在 Advisor 的适配器,那么同样需要对其进行封装
		for (AdvisorAdapter adapter : this.adapters) {
			// Check that it is supported.
			if (adapter.supportsAdvice(advice)) {
				return new DefaultPointcutAdvisor(advice);
			}
		}
		throw new UnknownAdviceTypeException(advice);
	}
}

紧接着,Spring将需要进行增强的对象都进行包装完成后,就需要开始创建代理了,我们来看下核心方法:

proxyFactory.getProxy(classLoader);
↓↓↓↓↓↓↓↓↓↓↓↓
public class ProxyFactory extends ProxyCreatorSupport {
	public Object getProxy(@Nullable ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}
}

这里我们可以看出有两个步骤:

  • 创建代理。
  • 获得代理。

2.4.1 创建代理createAopProxy

我们来深挖createAopProxy()方法:

protected final synchronized AopProxy createAopProxy() {
	if (!this.active) {
		activate();
	}
	return getAopProxyFactory().createAopProxy(this);
}
↓↓↓↓↓↓↓↓
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
	@Override
	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)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}
}

我们来分类介绍下上述代码中的判断条件。

  • config.isOptimize()

optimize:用来控制通过Cglib创建的代理是否使用激进的优化策略。

  • config.isProxyTargetClass()

proxyTargetClass:true时代表目标类本身被代理。而不是目标类的接口。此时创建Cglib代理。

  • hasNoUserSuppliedProxyInterfaces

代表是否存在代理接口。

(1) JDK和Cglib代理注意事项☆

1.若目标对象实现了接口:

  • 默认情况下采用JDK动态代理
  • 也可以强制使用Cglib代理。

2.若目标对象没有实现接口:

  • 必须采用Cglib库。Spring自动在JDKCglib代理之间切换。

3.两者的区别:

  • JDK动态代理只能对实现了接口的类生成代理,不能针对类。
  • Cglib代理针对类进行代理。对指定的类生成一个子类,覆盖其中的方法。(注意对应的方法不要声明为final,否则无法重写)

(2) JDK动态代理案例

1.创建业务接口。

public interface UserService {
    abstract void add();
}

2.创建业务接口的实现类。

public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("=============add===============");
    }
}

3.创建自定义的InvocationHandler,用于对接口提供的方法进行增强。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MyInvocationHandler implements InvocationHandler {
    // 目标对象
    private Object target;

    public MyInvocationHandler(Object target) {
        super();
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("==========before===========");
        // 执行目标方法
        Object res = method.invoke(target, args);
        System.out.println("==========after===========");
        return res;
    }

    // 获取目标对象的代理对象
    public Object getProxy() {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                target.getClass().getInterfaces(), this);
    }
}

4.Test类。

public class Test {
    @org.junit.Test
    public void test() {
        UserServiceImpl userService = new UserServiceImpl();
        // 实例化InvocationHandler
        MyInvocationHandler handler = new MyInvocationHandler(userService);
        // 根据目标对象生成代理对象
        UserService proxy = (UserService) handler.getProxy();
        proxy.add();
    }
}

结果如下:
在这里插入图片描述

(2) Cglib代理案例

1.创建拦截器。

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class MethodInterceptorImpl implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("Before invoke " + method);
        Object res = methodProxy.invokeSuper(obj, args);
        System.out.println("After invoke " + method);
        return res;
    }
}

2.测试类。

public class MyEnhancer {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(MyEnhancer.class);
        enhancer.setCallback(new MethodInterceptorImpl());

        MyEnhancer o = (MyEnhancer) enhancer.create();
        o.add();
        System.out.println(o);
    }

    public void add() {
        System.out.println("=====add=====");
    }
}

结果如下:可见最后生成了个由Cglib创建的对象实例。
在这里插入图片描述

2.4.2 获得代理getProxy

让我们回到源码分析这一块,我们可以看到,Spring中对于AopProxy接口的getProxy方法有两种实现:
在这里插入图片描述

(1) JDK动态代理原理

同样,我们先看JDK动态代理方式的getProxy

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
		}
		return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
	}
}

结合上文的JDK动态代理案例,我们知道其关键是创建自定义的InvocationHandler,并且实现了自己的getProxy方法。那么上述源码中,也恰恰是完成了这个操作。而具体的增强逻辑也想必是发生在invoke函数中。我们来看下JdkDynamicAopProxy.invoke()函数:

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
	@Override
	@Nullable
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object oldProxy = null;
		boolean setProxyContext = false;

		TargetSource targetSource = this.advised.targetSource;
		Object target = null;

		try {
			// 1.equals方法的处理
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				return equals(args[0]);
			}
			// 2.hashCode 方法的处理
			else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				return hashCode();
			}
			else if (method.getDeclaringClass() == DecoratingProxy.class) {
				return AopProxyUtils.ultimateTargetClass(this.advised);
			}
			// 3.Class类的 isAssignableFrom方法处理
			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;
			// 4.为了应付这种情况:目标对象内部的自我调用无法实施切面中的增强。那么此时通过该属性暴露代理
			if (this.advised.exposeProxy) {
				// Make invocation available if necessary.
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);
			// 5.获取当前方法的拦截器链
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
			// 6.若没有发现任何拦截器,则调用切点方法
			if (chain.isEmpty()) {
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				// 7.否则,封装拦截器
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// 8.执行拦截器链
				retVal = invocation.proceed();
			}
			// 返回结果
			Class<?> returnType = method.getReturnType();
			if (retVal != null && retVal == target &&
					returnType != Object.class && returnType.isInstance(proxy) &&
					!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
				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()) {
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}
}

这段代码的主要工作就是:

  1. 创建一个拦截器链,并使用ReflectiveMethodInvocation类进行链的封装。
  2. 调用ReflectiveMethodInvocation.proceed()进行拦截器的逐一调用。

我们来看下proceed()函数:

@Override
@Nullable
public Object proceed() throws Throwable {
	// 1.执行切点方法
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		return invokeJoinpoint();
	}
	// 2.获取下一个要执行的拦截器
	Object interceptorOrInterceptionAdvice =
			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
	if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
		// 3.动态匹配
		InterceptorAndDynamicMethodMatcher dm =
				(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
		Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
		if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
			return dm.interceptor.invoke(this);
		}
		else {
			// 匹配不成功,不执行
			return proceed();
		}
	}
	else {
		// 4.若是普通拦截器,直接调用。例如:ExposeInvocationInterceptor、MethodBeforeAdviceInterceptor
		// AspectJAfterAdvice等
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}

其主要工作就是:

  1. 维护调用链中的执行顺序,让其有序执行。
  2. 而具体的工资则委派给对应的增强器去执行。

(2) Cglib代理原理

形同JDK动态代理,我们从getProxy()函数讲起,这里我们讲另外的一个实现CglibAopProxy.getProxy()

class CglibAopProxy implements AopProxy, Serializable {
	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
		}

		try {
			// 1.从 advised 中获取目标对象的类对象
			Class<?> rootClass = this.advised.getTargetClass();
			Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

			Class<?> proxySuperClass = rootClass;
			// 2.若当前目标对象已经是由cglib生成的地阿里对象。即类中包含$$的字符串,那么获取目标对象的父类作为目标对象
			// 参考com.cglibaop.MyEnhancer$$EnhancerByCGLIB$$759803c3@4cdf35a9,
			if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
				proxySuperClass = rootClass.getSuperclass();
				Class<?>[] additionalInterfaces = rootClass.getInterfaces();
				for (Class<?> additionalInterface : additionalInterfaces) {
					this.advised.addInterface(additionalInterface);
				}
			}
			// 3.校验Class,打印出不能代理的方法名。比如final和static的方法不能被增强。因为Cglib使用继承的方式去实现。
			validateClassIfNecessary(proxySuperClass, classLoader);
			// 4.创建Enhancer类,作为主要的操作类
			Enhancer enhancer = createEnhancer();
			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);
				if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
					enhancer.setUseCache(false);
				}
			}
			// 5.配置超类,代理类的实现接口、回调函数等
			enhancer.setSuperclass(proxySuperClass);
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
			// 6.设置拦截器
			Callback[] callbacks = getCallbacks(rootClass);
			Class<?>[] types = new Class<?>[callbacks.length];
			for (int x = 0; x < types.length; x++) {
				types[x] = callbacks[x].getClass();
			}
			// fixedInterceptorMap only populated at this point, after getCallbacks call above
			enhancer.setCallbackFilter(new ProxyCallbackFilter(
					this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
			enhancer.setCallbackTypes(types);
			// 7.通过Enhancer生成代理对象,并设置回调
			return createProxyClassAndInstance(enhancer, callbacks);
		}
		// ...catch
	}
}	

上述代码中,主要做这么几件事:

  1. 目标类和拦截器的获取。
  2. Enhancer的创建和相关属性设置。
  3. 拦截器的设置。
  4. 创建代理对象。

其中第三步比较重要,我们来看下拦截器链的设置过程:

Callback[] callbacks = getCallbacks(rootClass);

private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
		// ..省略
		// 将拦截器封装到DynamicAdvisedInterceptor中
		Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
		// ..省略
		// 2.将拦截器链加入到Callback中
		Callback[] mainCallbacks = new Callback[] {
				aopInterceptor,  // for normal advice
				targetInterceptor,  // invoke target without considering advice, if optimized
				new SerializableNoOp(),  // no override for methods mapped to this
				targetDispatcher, this.advisedDispatcher,
				new EqualsInterceptor(this.advised),
				new HashCodeInterceptor(this.advised)
		};
		// ..省略
	}

不知道各位小伙伴还记得本文的Cglib案例不,里面的代码是这样的:

public static void main(String[] args) {
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(MyEnhancer.class);
    enhancer.setCallback(new MethodInterceptorImpl());

    MyEnhancer o = (MyEnhancer) enhancer.create();
    o.add();
    System.out.println(o);
}

我们可以发现Cglib对于方法的拦截是通过将自定义的拦截器加入到Callback中并调用代理时,通过激活intercept方法来实现。

而源码中我们可以发现,Spring将拦截器都加入到了DynamicAdvisedInterceptor这个类中,而该类又是MethodInterceptor的实现类。因此具体的Cglib方式的AOP代理必然在其中实现:

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
	@Override
	@Nullable
	public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		Object oldProxy = null;
		boolean setProxyContext = false;
		Object target = null;
		TargetSource targetSource = this.advised.getTargetSource();
		try {
			// 同JDK代理,处理一些自调用的特殊情况,暴露对象
			if (this.advised.exposeProxy) {
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);
			// 1.获取拦截器链
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
			Object retVal;
			// 2.若拦截器为空,且方法是可以公共访问的。直接调用源方法
			if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = methodProxy.invoke(target, argsToUse);
			}
			else {
				// 3.进入链中,和jdk 动态代理实现是类似的,只是MethodInvocation实现类不同而已
				retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
			}
			retVal = processReturnType(proxy, target, method, retVal);
			return retVal;
		}
		finally {
			if (target != null && !targetSource.isStatic()) {
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				// Restore old proxy.
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}
}

我们看下第三步,对于拦截器的封装,Cglib这里使用的是CglibMethodInvocation类,而JDK动态代理方式则使用的ReflectiveMethodInvocation类。

注意:

  • CglibMethodInvocation继承了ReflectiveMethodInvocation类。
  • 但是并没有重写proceed方法,因此后面的逻辑和JDK动态代理一致。

到这里,创建完代理之后,AOP的实现也就完成了。只要我们自己编码的时候调用相关的方法,就会实现逻辑的增强了。

三. 总结(带流程图)☆

在这里插入图片描述

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-30 18:09:58  更:2022-03-30 18:11:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:43:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码