前面说过:AOP是一种编程思想,用于将程序中的横切关注点(如事务、日志)从业务逻辑代码中分离出来,以提高代码的可重用性和可维护性。Spring框架对其进行了实现。在Spring中AOP是通过代理模式实现的,即在运行时动态的生成一个代理,这个代理类会拦截目标对象的方法调用,并在方法执行前后添加响应的横切逻辑。
通过这一段话,我们只能知道Spring框架使用动态代理技术对AOP进行了实现。那Spring究竟是怎么实现的呢?下面就根据源码一步步地揭开Spring AOP的神秘面纱吧。在开始跟踪之前,先来看一个问题吧:假设现在没有实现AOP的Spring框架,公司领导又点名要你给系统增加日志功能,作为开发者你会怎么做(需要说明的是要添加日志的接口非常多,并且这个日志要足够灵活,能够支持后面其他同事开发的新接口。那该怎么高效、安全的实现这个需求呢?答案肯定是AOP!)。思路大概是这样的(这里有点事后诸葛亮,不过还是想通过这个让大家有个基本的认识,以便后面跟踪Spring源码时能够快速理解。该思路参照了字符串搜索表达式,同时用到了反射和动态代理):
- 配置匹配模式,即匹配将被增强的方法(即目标方法)
- 编写增强方法,即要对目标方法做的增强逻辑,比如本例中的日志打印逻辑
- 为目标创建代理,然后使用该代理
参照上述两点,落地开发的详细步骤为:
- 匹配模式解析,即将该匹配模式保存下来,以便后面匹配时使用
- 被增强方法匹配逻辑,即用配置的匹配模式找到要被增强的类或方法,并将其存储在Map中
- 增强方法解析及增强方法与匹配模式关系处理,即将增强方法解析出来,并为该增强方法指定一定的匹配模式
- 为目标方法创建一个代理,然后在该代理类相关方法的前后设置相关增强方法
- 调用代理调用目标方法
这里要注意一下:被增强的方法,即目标方法,是处理实际业务的方法(比如上一节TransferService类中的check(…)方法);匹配模式,即切入点,它是一个字符串表达式,用于匹配合适的目标方法(比如上一节CustomerAspect中的pointcut(…)方法);增强方法,即切面,是对目标方法的扩展,比如日志打印、事务等(比如上一节CustomerAspect类中的around(…)方法、before(…)方法、after(…)方法)。
下面我们从@EnableAspectJAutoProxy注解开始跟踪。该注解详细实现代码中有一个注解@Import(AspectJAutoProxyRegistrar.class),通过该注解系统会自动向Spring容器中注入一个类型为AnnotationAwareAspectJAutoProxyCreator的对象。我们先看一下这两个注解的代码实现:
从这里继续向下跟踪会看到如下图所示的代码:
前面提到过,这里会向容器中注入AnnotationAwareAspectJAutoProxyCreator对象,该类的继承结构如下图所示:
从这幅图可以看到AbstractAutoProxyCreator继承了BeanPostProcessor接口。该接口中主要定义了两个方法:
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
由此可知继承该接口的实现类的主要作用是在注册到Spring中的Bean的初始化前后做一些处理,比如本节要讲的代理对象就是在postProcessAfterInitialization()方法中创建的。接下来主要看一下AbstractAutoProxyCreator类中的postProcessAfterInitialization()方法的代码,其代码如下所示:
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyBeanReferences.remove(cacheKey) != bean) {
// 主要关注这里
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
在上面代码中我们主要关注wrapIfNecessary()方法。该方法的代码如下所示:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 重点关注这个 shouldSkip() 方法,该方法最终会调用BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors()以解析@Aspect注解修饰的类,其中用@Around、@After、@Before等注解修饰的方法会被解析
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 这段代码的主要逻辑是提取适用该对象的Advice和Advisor。
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
对于这个方法我想按照以下顺序梳理:解析(主要解析系统中配置的切面和切点)、创建代理(将符合切点的方法和切面进行组合,并用代理对象包装)。
1 解析
这里主要梳理Spring如何解析用@Aspect修饰的类以及@Around、@After、@Before等注解修饰的方法。下面首先看一下AspectJAwareAdvisorAutoProxyCreator#shouldSkip(Class<?> beanClass, String beanName)方法,其源码如下所示:
@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
// 该方法的主要作用是查找所有候选的Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor pointcutAdvisor &&
pointcutAdvisor.getAspectName().equals(beanName)) {
return true;
}
}
return super.shouldSkip(beanClass, beanName);
}
这里主要看findCandidateAdvisors()方法,该方法的源码如下所示(注意这个源码位于AspectJAwareAdvisorAutoProxyCreator类中):
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
由于Spring容器启动时注入的实际类型为AnnotationAwareAspectJAutoProxyCreator,所以AspectJAwareAdvisorAutoProxyCreator#shouldSkip(Class<?> beanClass, String beanName)中的List<Advisor> candidateAdvisors = findCandidateAdvisors()最终调用的是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) {
// 重点关注这里
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
这里主要看this.aspectJAdvisorsBuilder.buildAspectJAdvisors()这段代码,该方法位于BeanFactoryAspectJAdvisorsBuilder类中,其源码如下所示:
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<>();
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
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, false);
if (beanType == null) {
continue;
}
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 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;
}
从上述代码可以知道,这段代码会遍历Spring容器中注册的所有beanName,然后判断该bean是否被@Aspect注解修饰,如果是则继续解析,否则跳过,具体如下图所示:
上述代码中的List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory)是真正解析的入口。其代码(位于ReflectiveAspectJAdvisorFactory类中)如下所示:
@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 ArrayList<>();
for (Method method : getAdvisorMethods(aspectClass)) {
// Prior to Spring Framework 5.2.7, advisors.size() was supplied as the declarationOrderInAspect
// to getAdvisor(...) to represent the "current position" in the declared methods list.
// However, since Java 7 the "current position" is not valid since the JDK no longer
// returns declared methods in the order in which they are declared in the source code.
// Thus, we now hard code the declarationOrderInAspect to 0 for all advice methods
// discovered via reflection in order to support reliable advice ordering across JVM launches.
// Specifically, a value of 0 aligns with the default value used in
// AspectJPrecedenceComparator.getAspectDeclarationOrder(Advisor).
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, 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;
}
该方法主要做了两件事:1.解析@Aspect注解修饰的类中被@Around、@After、@Before修饰的方法;2.解析@Aspect注解修饰的类中的字段。第一步解析调用的是ReflectiveAspectJAdvisorFactory类中的getAdvisor()方法,该方法主要做了下面几件事:
- 校验(个人理解就是校验当前Bean对应的类是否被@Aspect注解修饰)
- 解析切入点,即AspectJExpressionPointcut,也就是@Around等注解中指定的切入点
- 创建InstantiationModelAwarePointcutAdvisorImpl对象,这里会创建实际的通知类型,即Advice
getAdvisor()方法的主要代码如下所示:
@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
接下来继续看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(AspectJExpressionPointcut pointcut)方法的这行,该方法源码如下所示:
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);
}
该方法最终会调用AspectJAdvisorFactory类的getAdvice()方法,其源码如下所示:
@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
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
AbstractAspectJAdvice springAdvice;
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut -> {
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
}
case AtAround -> springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
case AtBefore -> springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
case AtAfter -> springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
case AtAfterReturning -> {
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
}
case AtAfterThrowing -> {
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
}
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;
}
对于这段代码主要关注下图所示的地方(这里会根据枚举类型创建不同的Advice):
至此Spring AOP解析的步骤都梳理完成了。下面继续看一下解析过程中涉及的两个主要角色吧!它们分别为:Advisor、Advice。Advisor是Spring AOP的顶级接口,上面看到的InstantiationModelAwarePointcutAdvisorImpl就实现了该接口,其包含了通知(Advice)和适用判断的过滤器。考虑到通用性,过滤规则由其子接口定义,比如IntroductionAdvisor和PointcutAdvisor,过滤器用于判断bean是否需要被代理。Advice被称为通知,也即在调用目标方法时我们想要做的处理逻辑,比如处理事务、打印日志等,比如上节示例中提到的前置通知、后置通知和环绕通知等。通过源码也可以知道Spring AOP提供的通知主要有这样几类:AtAround、AtBefore、 AtAfter、AtAfterReturning、AtAfterThrowing。这些都定义在Spring的AspectJAnnotationType枚举中。该枚举的源码如下所示:
protected enum AspectJAnnotationType {
AtPointcut, AtAround, AtBefore, AtAfter, AtAfterReturning, AtAfterThrowing
}
下图是Spring AOP常见的几种通知的类结构图:
这里要再明确这样一个点:Advisor包含通知(拦截器),是Spring中AOP的顶级接口,不过这个接口实现类中还需要包含一个aop适用判断的过滤器。考虑到通用性,过滤规则由其子接口定义,比如IntroductionAdvisor和PointcutAdvisor,过滤器用于判断bean是否需要被代理。下面两幅图就展示了IntroductionAdvisor、PointcutAdvisor及其子类的类结构。还记得InstantiationModelAwarePointcutAdvisorImpl对象的创建吧!这里再看以下这段代码:
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
下图为Pointcut接口的实现类AspectJExpressionPointcut的类结构图。Pointcut可以被称作切点,是过滤器的一种实现,用于匹配过滤哪些类或哪些方法需要被切面处理,其实现了ClassFilter和MethodMatcher接口。这个类在定义PointcutAdvisor(比如创建上图InstantiationModelAwarePointcutAdvisorImpl类型对象时,会向其构造方法中传递一个AspectJExpressionPointcut类型的对象)类型的对象时会用到。
从上图可以看出AspectJExpressionPointcut实现了ClassFilter和MethodMatcher接口。其中ClassFilter是限制切入点或引入点与给定目标类集的匹配的筛选器,属于过滤器的一种实现。过滤筛选合适的类,有些类不需要被处理。MethodMatcher是方法匹配器,定义方法匹配规则,也是过滤器的一种实现,其主要用于判断哪些方法需要使用AOP。不知道你有没有注意到,AspectJExpressionPointcut类中有这样一段代码:
看着是不是有些熟悉,还记得Spring AOP第一篇中切入点的定义吗?对,就是@Pointcut("execution(* org.com.chinasofti.springtransaction.service.*.*(..))")注解中的execution。这组定义涉及到了切点的定义,这里就不再梳理了,如果想深入了解配置规则,可以参照下面这篇博客:https://www.cnblogs.com/cunkouzh/p/5844816.html。
2 创建代理
本小节主要梳理Spring AOP代理类的创建过程。代码入口位于AbstractAutoProxyCreator类的wrapIfNecessary(Object bean, String beanName, Object cacheKey)方法中。如下图所示:
接下来主要关注createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource)方法的处理逻辑,该方法位于AbstractAutoProxyCreator类中,其详细代码如下所示:
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
return buildProxy(beanClass, beanName, specificInterceptors, targetSource, false);
}
这段代码非常简单,主要是调用AbstractAutoProxyCreator的buildProxy()方法去创建代理,其具体代码如下所示:
private Object buildProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource, boolean classOnly) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory clbf) {
AutoProxyUtils.exposeTargetClass(clbf, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (proxyFactory.isProxyTargetClass()) {
// Explicit handling of JDK proxy targets and lambdas (for introduction advice scenarios)
if (Proxy.isProxyClass(beanClass) || ClassUtils.isLambdaClass(beanClass)) {
// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
for (Class<?> ifc : beanClass.getInterfaces()) {
proxyFactory.addInterface(ifc);
}
}
}
else {
// No proxyTargetClass flag enforced, let's apply our default checks...
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// Use original ClassLoader if bean class not locally loaded in overriding class loader
ClassLoader classLoader = getProxyClassLoader();
if (classLoader instanceof SmartClassLoader smartClassLoader && classLoader != beanClass.getClassLoader()) {
classLoader = smartClassLoader.getOriginalClassLoader();
}
return (classOnly ? proxyFactory.getProxyClass(classLoader) : proxyFactory.getProxy(classLoader));
}
通过代码不难看出,其首先创建一个代理工厂对象,即ProxyFactory proxyFactory = new ProxyFactory(),接着从容器中拿到适配指定beanName的Advisor,即前面提到的包含通知和适配过滤器的对象,这里拿到的是一组对象,其实际类型就是前面提到的InstantiationModelAwarePointcutAdvisorImpl类型(这里参照的是前一节的示例),最后调用ProxyFactory类的getProxy()方法创建代理对象。接下来看一下PoxyFactory类的getProxy()方法,其具体代码如下所示:
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
该类会调用其父类ProxyCreatorSupport类的createAopProxy(),其代码如下所示:
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
这个方法(指的是createproxy())先调用本类中的getAopProxyFactory()方法获取AopProxyFactory类型的对象aopProxyFactory(该对象的初始化实在ProxyCreatorSupport类的构造方法中做的,具体如下图所示)
接着这个方法(指的是createproxy())又继续DefaultAopProxyFactory(该类实现了AopProxyFactory接口)类的createAopProxy()方法,其具体代码如下所示:
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
从这段代码可以看到我们常见的JDK动态代理和CGLIB动态代理。根据debug结果,Spring使用CGLIB来创建目标对象的代理对象,即使用ObjenesisCglibAopProxy对象来创建后面的代理对象。注意该类继承了CglibAopProxy类。接着继续回到PoxyFactory类的getProxy()方法中,继续跟踪到getProxy()方法,此时会跳转到CglibAopProxy类的getProxy()方法中,该方法继续调用本类的buildProxy ()方法。该方法源码如下所示:
private Object buildProxy(@Nullable ClassLoader classLoader, boolean classOnly) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader smartClassLoader &&
smartClassLoader.isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setAttemptLoad(true);
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
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
ProxyCallbackFilter filter = new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset);
enhancer.setCallbackFilter(filter);
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
// ProxyCallbackFilter has method introspection capability with Advisor access.
try {
return (classOnly ? createProxyClass(enhancer) : createProxyClassAndInstance(enhancer, callbacks));
}
finally {
// Reduce ProxyCallbackFilter to key-only state for its class cache role
// in the CGLIB$CALLBACK_FILTER field, not leaking any Advisor state...
filter.advised.reduceToAdvisorKey();
}
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
该方法首先创建了Enhancer对象,然后进行一些属性设置,最后调用createProxyClassAndInstance(enhancer, callbacks))创建对应的代理对象。好了,先到这里吧!先跟大家说声对不起,因为我觉得Spring AOP涉及的知识点和编码逻辑还有很多,认知有限的我,真的无法向大家一一介绍,不过后续我还会根据需要对此知识点进行持续更新,也欢迎大家对文章中的不足提出宝贵的意见。在这里先谢谢了!