Spring之AOP源码(二)

书接上文

文章目录

    • 一、简介
      • 1. 前文回顾
      • 2. 知识点补充
    • 二、ProxyFactory源码分析
      • 1. ProxyFactory
      • 2. JdkDynamicAopProxy
      • 3. ObjenesisCglibAopProxy
    • 三、 Spring AOP源码分析

一、简介

1. 前文回顾

前面我们已经介绍了AOP的基本使用方法以及基本原理,但是还没有涉及源码层面,这篇文章就深度分析一下SpringAOP的底层源码。

2. 知识点补充

  • TargetSource

在我们日常的AOP中,被代理对象就是Bean对象,是由BeanFactory给我们创建出来的,但是 Spring AOP中提供了TargetSource机制,可以让我们用来自定义逻辑来创建被代理对象。让我们通过一个简单的案例来说明如何使用 TargetSource。假设我们有一个服务类 UserService,它负责处理用户的业务逻辑,而我们希望在不同的场景下使用不同的实例。

定义目标类:

@Component
public class UserService {public void performAction() {System.out.println("Performing action in UserService");}
}

**自定义 TargetSource:**

@Component
public class CustomTargetSource implements TargetSource {@Overridepublic Class<?> getTargetClass() {return UserService.class;}@Overridepublic boolean isStatic() {return false;}@Overridepublic Object getTarget() throws Exception {// 在此处根据业务逻辑返回不同的目标对象实例// 这里简单地返回一个新的 UserService 实例return new UserService();}@Overridepublic void releaseTarget(Object target) throws Exception {// 可以在这里进行一些资源的释放操作}
}

配置切面:

@Aspect
@Component
public class CustomAspect {@Autowiredprivate CustomTargetSource customTargetSource;@Before("execution(* com.zhouyu.service.UserService.*(..))")public void beforeUserServiceMethod() throws Exception {// 在方法执行前,使用 TargetSource 切换目标对象Object target = customTargetSource.getTarget();// 执行你的逻辑}
}

@Lazy注解生成代理对象的时候,底层就使用到了TargetSource

protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final @Nullable String beanName) {BeanFactory beanFactory = getBeanFactory();Assert.state(beanFactory instanceof DefaultListableBeanFactory,"BeanFactory needs to be a DefaultListableBeanFactory");final DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory) beanFactory;TargetSource ts = new TargetSource() {@Overridepublic Class<?> getTargetClass() {return descriptor.getDependencyType();}@Overridepublic boolean isStatic() {return false;}@Overridepublic Object getTarget() {Set<String> autowiredBeanNames = (beanName != null ? new LinkedHashSet<>(1) : null);Object target = dlbf.doResolveDependency(descriptor, beanName, autowiredBeanNames, null);if (target == null) {Class<?> type = getTargetClass();if (Map.class == type) {return Collections.emptyMap();}else if (List.class == type) {return Collections.emptyList();}else if (Set.class == type || Collection.class == type) {return Collections.emptySet();}throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(),"Optional dependency not present for lazy injection point");}if (autowiredBeanNames != null) {for (String autowiredBeanName : autowiredBeanNames) {if (dlbf.containsBean(autowiredBeanName)) {dlbf.registerDependentBean(autowiredBeanName, beanName);}}}return target;}@Overridepublic void releaseTarget(Object target) {}};

二、ProxyFactory源码分析

1. ProxyFactory

前面说过这个类是Spring底层对JDK以及Cglib动态代理的底层封装,下面我们分析一下这个类底层是怎么做的。

public static void main(String[] args) {UserService target = new UserService();//创建代理工厂ProxyFactory proxyFactory=new ProxyFactory();//设置代理对象proxyFactory.setTarget(target);//设置代理逻辑proxyFactory.addAdvice(new MethodBeforeAdvice() {@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println("before");}});//返回代理对象UserService proxy = (UserService) proxyFactory.getProxy();proxy.test();}

上面代码是我前面给出的一个案例,其中UserService proxy = (UserService) proxyFactory.getProxy();就返回了一个代理对象。进入proxyFactory.getProxy方法。

public Object getProxy() {return createAopProxy().getProxy();}

createAopProxy()就是用来创建AOP代理的,进入该方法。

protected final synchronized AopProxy createAopProxy() {if (!this.active) {activate();}// 默认为DefaultAopProxyFactoryreturn getAopProxyFactory().createAopProxy(this);}

然后调用createAopProxy方法。

public interface AopProxyFactory {AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;
}

我们看AopProxyFactory的默认实现类DefaultAopProxyFactory是怎么实现该方法的。

@Overridepublic AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {// 如果ProxyFactory的isOptimize为true,Spring认为cglib比jdk动态代理要快// 或者isProxyTargetClass为true,// 或者被代理对象没有实现接口,// 或者只实现了SpringProxy这个接口// 那么则利用Cglib进行动态代理,但如果被代理类是接口,或者被代理类已经是进行过JDK动态代理而生成的代理类了则只能进行JDK动态代理// 其他情况都会进行JDK动态代理,比如被代理类实现了除SpringProxy接口之外的其他接口// 是不是在GraalVM虚拟机上运行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);}}

上面代码就是在判断当前到底使用jdk动态代理还是cglib动态代理:

  • !NativeDetector.inNativeImage():如果当前的JVM是GraalVM那么就直接使用JDK动态代理
  • config.isOptimize():表示你是否需要优化(如果需要优化就会使用cglib),然后config就是ProxyFactory本身
  • config.isProxyTargetClass():表示代理的目标类是否时接口
  • hasNoUserSuppliedProxyInterfaces(config):判断ProxyFactory是否提供了接口setInterfaces,如果提供了这个就会返回false
  • if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) :首先判断被代理的类是否是一个接口,然后判断你现在代理的目标类,是否是jdk产生的代理类

通过上面方法createAopProxy()就返回了JdkDynamicAopProxyObjenesisCglibAopProxy这两个对象其中之一。然后,回到getProxy方法,它就会调用createAopProxy().getProxy();去生成正在的代理对象。

2. JdkDynamicAopProxy

通过上面代码如果我们最后决定使用的代理类是JdkDynamicAopProxy,那么就会由这个类生产代理对象。首先我们看看JDK是如何生成我们的代理对象的,关键是getProxy方法。

@Overridepublic Object getProxy() {return getProxy(ClassUtils.getDefaultClassLoader());}@Overridepublic Object getProxy(@Nullable ClassLoader classLoader) {if (logger.isTraceEnabled()) {logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());}// this实现了InvocationHandlerreturn Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);}

很简单就是使用newProxyInstance创建了一个代理对象,this就实现了InvocationHandler。当我们执行代理对象的指定方法时,就会进入invoke方法,我们仔细分析一下这个方法底层:

@Override@Nullablepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object oldProxy = null;boolean setProxyContext = false;// 拿到被代理对象(targetSource) TargetSource targetSource = this.advised.targetSource;Object target = null;try {// 如果接口中没有定义equals()方法,那么则直接调用,不走代理if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {// The target does not implement the equals(Object) method itself.return equals(args[0]);}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);}else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&method.getDeclaringClass().isAssignableFrom(Advised.class)) {// Service invocations on ProxyConfig with the proxy config...// 也是直接调用Advised接口中的方法,不走代理逻辑// 其实就是利用代理对象获取ProxyFactory中的信息return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);}Object retVal;// 如果ProxyFactory的exposeProxy为true,则将代理对象设置到currentProxy这个ThreadLocal中去,这样整个线程的执行过程中我们都可以拿到这个代理对象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.// 代理对象在执行某个方法时,根据方法筛选出匹配的Advisor,并适配成InterceptorList<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.// 如果没有Advice,则直接调用对应方法Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);}else {// We need to create a method invocation...MethodInvocation invocation =new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);// 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);}}}

我们知道在AOP中,我们执行指定方法时,这个方法可能会添加多个Advisor,组成一条链,在执行该方法的实际逻辑之前,首先需要执行完所有的Advisor逻辑。而生成这个链(本质上就是list集合)就是下面的代码:

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {// 代理对象在执行某个方法时,会根据当前ProxyFactory中所设置的Advisor根据当前Method再次进行过滤MethodCacheKey cacheKey = new MethodCacheKey(method);// 注意这个List,表示的就是Advice链List<Object> cached = this.methodCache.get(cacheKey);if (cached == null) {cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);this.methodCache.put(cacheKey, cached);}return cached;}

关键就是调用了getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);,这里有一个点就是前面我们使用到的所有Advice,不管是前置通知还是后置通知或者是环绕通知,它们其实类时本质上都是MethodInterceptor类型。

@Overridepublic 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.AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();// 从ProxyFactory中拿到所设置的Advice(添加时被封装成了DefaultPointcutAdvisor)// 添加的时候会控制顺序//取到当前所有的Advisor(切点+advice)//我们在使用porxyFacoty添加advice时会在底层转换为Advisor对象,切点默认是所有方法匹配Advisor[] advisors = config.getAdvisors();List<Object> interceptorList = new ArrayList<>(advisors.length);Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());Boolean hasIntroductions = null;//遍历当前proxyFactory所有的Advisorfor (Advisor advisor : advisors) {if (advisor instanceof PointcutAdvisor) {// Add it conditionally.PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;// 先匹配类if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {// 再匹配方法MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();boolean match;if (mm instanceof IntroductionAwareMethodMatcher) {if (hasIntroductions == null) {hasIntroductions = hasMatchingIntroductions(advisors, actualClass);}match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);}else {match = mm.matches(method, actualClass);}if (match) {// 如果匹配则将Advisor封装成为Interceptor,当前Advisor中的Advice可能即是MethodBeforeAdvice,也是ThrowsAdviceMethodInterceptor[] interceptors = registry.getInterceptors(advisor);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.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));}}else {interceptorList.addAll(Arrays.asList(interceptors));}}// 最终,interceptorList中存储的是当前正在执行的Method所匹配的MethodInterceptor,可能动态的,也可能是非动态的,// 找到Method所匹配的MethodInterceptor后,就会开始调用这些MethodInterceptor,如果是动态的,会额外进行方法参数的匹配}}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 {// 将Advisor封装成为InterceptorInterceptor[] interceptors = registry.getInterceptors(advisor);interceptorList.addAll(Arrays.asList(interceptors));}}return interceptorList;}

首先我们看下面这句代码

if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {

上面这句代码关键是通过pointcutAdvisor.getPointcut()获得当前的切点,然后调用切点的getClassFilter()获得要拦截的目标类,然后判断是否和当前类actualClass匹配,一句话说就是上面if就是判断类型匹配的。如果类型匹配后就会开始匹配方法:

MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {if (hasIntroductions == null) {hasIntroductions = hasMatchingIntroductions(advisors, actualClass);}match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);}else {match = mm.matches(method, actualClass);}

关键是调用match = mm.matches(method, actualClass);这句代码判断当前的方法和要拦截的方法是否匹配。如果前面两个条件都符合,就会执行下面的逻辑:

if (match) {// 如果匹配则将Advisor里面的advice封装成为Interceptor,当前Advisor中的Advice可能即是MethodBeforeAdvice,也是ThrowsAdviceMethodInterceptor[] interceptors = registry.getInterceptors(advisor);//如果方法匹配起的isRuntime属性是trueif (mm.isRuntime()) {for (MethodInterceptor interceptor : interceptors) {interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));}}else {interceptorList.addAll(Arrays.asList(interceptors));}
}

MethodInterceptor[] interceptors = registry.getInterceptors(advisor);首先将当前的Advisor转换为一个MethodInterceptor对象。然后它会判断你是否设置了方法匹配器的isRuntime是否为true,为true就会对MethodInterceptor进行二次封装,这么做的目的就是为了处理如果我们调用的目标类的目标方法有参数,我们还要考虑参数匹配的情况,会被封装到InterceptorAndDynamicMethodMatcher这个MethodInterceptor对象中。

@Overridepublic MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {List<MethodInterceptor> interceptors = new ArrayList<>(3);//拿到当前advisor的advice对象Advice advice = advisor.getAdvice();//如果当前的advice本来就是MethodInterceptor类型,直接加入数组中if (advice instanceof MethodInterceptor) {interceptors.add((MethodInterceptor) advice);}// 将Advice适配成MethodInterceptorfor (AdvisorAdapter adapter : this.adapters) {if (adapter.supportsAdvice(advice)) {interceptors.add(adapter.getInterceptor(advisor));}}if (interceptors.isEmpty()) {throw new UnknownAdviceTypeException(advisor.getAdvice());}return interceptors.toArray(new MethodInterceptor[0]);}

上面源码其实就是将一个Advisor中的所有Advice封装到MethodInterceptor[]数组中,如果某个Advice类型是MethodInterceptor,那它就可以直接被添加到这个数组中,否则就要通过下面代码进行适配:

for (AdvisorAdapter adapter : this.adapters) {if (adapter.supportsAdvice(advice)) {interceptors.add(adapter.getInterceptor(advisor));}}
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());}

可以看出适配器有三种,分别是MethodBeforeAdviceAdapterAfterReturningAdviceAdapterThrowsAdviceAdapter,分别对应前面说到的前置、后置和异常通知。然后调用adapter.supportsAdvice(advice),使用适配器supportsAdvice,判断当前的Advice是否适配。

在这里插入图片描述
可以看出每个适配器都实现了该方法,我们随便拿出其中一个,看看是如何适配的。

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

可以发现直接就是instanceof进行类型判断。进行类型判断后,如果符合,现在就是需要将当前的Advice类型转换为MethodInterceptor类型,这个同样是适配器完成的adapter.getInterceptor(advisor):

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

我们知道不同的Advice执行顺序不同的,而且前面反复强调Advice最后都会转换为MethodInterceptor对象,然后最后通过这个对象调用相应的通知方法。比方说上面的AfterReturningAdviceInterceptor就是一个MethodInterceptor对象,我们看看它底层是如何封装Advice的。

public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {private final AfterReturningAdvice advice;public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {Assert.notNull(advice, "Advice must not be null");this.advice = advice;}@Override@Nullablepublic Object invoke(MethodInvocation mi) throws Throwable {Object retVal = mi.proceed();this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());return retVal;}}

关键是invoke函数,Object retVal = mi.proceed();这个就执行了代理目标的实际方法,advice.afterReturning(这个就是执行了代理逻辑。这就是MethodInterceptor最核心的逻辑。到此MethodInterceptor就封装完毕了。回到前面的invoke方法。我们获得Advisor链之后就会执行下面的逻辑:

if (chain.isEmpty()) {// 如果没有Advice,则直接调用对应方法Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}

上面代码的意思是如果我们没有加入任何Advisor,那么就会直接调用目标类的目标方法逻辑。否则就会执行下面的代码:

else {// We need to create a method invocation...MethodInvocation invocation =new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);// Proceed to the joinpoint through the interceptor chain.retVal = invocation.proceed();
}

上面代码首先将MethodInterceptor数组封装为一个MethodInvocation对象,然后调用invocation.proceed,开始执行MethodInterceptor底层真正的逻辑。

@Override@Nullablepublic Object proceed() throws Throwable {// We start with an index of -1 and increment early.// currentInterceptorIndex初始值为-1,每调用一个interceptor就会加1// 当调用完了最后一个interceptor后就会执行被代理方法if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}// currentInterceptorIndex初始值为-1Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);// 当前interceptor是InterceptorAndDynamicMethodMatcher,则先进行匹配,匹配成功后再调用该interceptor// 如果没有匹配则递归调用proceed()方法,调用下一个interceptorif (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {// Evaluate dynamic method matcher here: static part will already have// been evaluated and found to match.InterceptorAndDynamicMethodMatcher dm =(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());// 动态匹配,根据方法参数匹配if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {return dm.interceptor.invoke(this);}else {// Dynamic matching failed.// Skip this interceptor and invoke the next in the chain.// 不匹配则执行下一个MethodInterceptorreturn proceed();}}else {// It's an interceptor, so we just invoke it: The pointcut will have// been evaluated statically before this object was constructed.// 直接调用MethodInterceptor,传入this,在内部会再次调用proceed()方法进行递归// 比如MethodBeforeAdviceInterceptorreturn ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}}

我们先看下面代码:

if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}

this.currentInterceptorIndex ReflectiveMethodInvocation类的一个属性,默认值是-1,his.interceptorsAndDynamicMethodMatchers也是该类的一个属性,在构造ReflectiveMethodInvocation对象时会将我们前面照到的所有MethodInterceptor赋值给这个属性。这里我们先不说这个if判断的作用,先往后执行代码。

Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

上面代码就是取出下一个MethodInterceptor。然后继续看后面代码

// 当前interceptor是InterceptorAndDynamicMethodMatcher,则先进行匹配,匹配成功后再调用该interceptor// 如果没有匹配则递归调用proceed()方法,调用下一个interceptorif (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {// Evaluate dynamic method matcher here: static part will already have// been evaluated and found to match.InterceptorAndDynamicMethodMatcher dm =(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());// 动态匹配,根据方法参数匹配if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {return dm.interceptor.invoke(this);}else {// Dynamic matching failed.// Skip this interceptor and invoke the next in the chain.// 不匹配则执行下一个MethodInterceptorreturn proceed();}}else {// It's an interceptor, so we just invoke it: The pointcut will have// been evaluated statically before this object was constructed.// 直接调用MethodInterceptor,传入this,在内部会再次调用proceed()方法进行递归// 比如MethodBeforeAdviceInterceptorreturn ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}

如果当前的MethodInterceptorInterceptorAndDynamicMethodMatcher类型,它需要进行参数匹配。如果不是该类型直接调用该MethodInterceptor的invoke方法。

	@Override@Nullablepublic Object invoke(MethodInvocation mi) throws Throwable {Object retVal = mi.proceed();this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());return retVal;}

然后Object retVal = mi.proceed();又调用了proceed方法,就开始执行下一个MethodInterceptor(有点套娃的意思),直到所有的MethodInterceptor执行完后,就回到第一个if判断了。

if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}

现在进入invokeJoinpoint方法。

@Nullableprotected Object invokeJoinpoint() throws Throwable {return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);}
@Nullablepublic static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)throws Throwable {// Use reflection to invoke the method.try {ReflectionUtils.makeAccessible(method);// 执行普通对象的方法,注意和@Configuration产生的代理对象的逻辑区别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);}}

关键就是这句代码return method.invoke(target, args)执行了被代理对象的指定方法。上面就是Spring AOP代理逻辑的执行过程。

3. ObjenesisCglibAopProxy

前面分析了JDK的动态代理,Cglib动态代理其实流程和这个差不多,我们简单的过一下。首先进入getProxy源码

@Overridepublic Object getProxy(@Nullable ClassLoader classLoader) {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;// 如果被代理类本身就已经是Cglib所生成的代理类了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);//定义增强器Enhancer enhancer = createEnhancer();if (classLoader != null) {//设置类加载器enhancer.setClassLoader(classLoader);if (classLoader instanceof SmartClassLoader &&((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {enhancer.setUseCache(false);}}// 被代理类,代理类的父类enhancer.setSuperclass(proxySuperClass);// 代理类额外要实现的接口enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));// 获取和被代理类所匹配的AdvisorCallback[] 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 aboveenhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));enhancer.setCallbackTypes(types);// Generate the proxy class and create a proxy instance.return createProxyClassAndInstance(enhancer, callbacks);}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() failedthrow new AopConfigException("Unexpected AOP exception", ex);}}

和jdk动态代理不同,Cglib动态代理所有的Advisro都会放在一个Callback集合中。

Callback[] callbacks = getCallbacks(rootClass);

我们看看Cglib是怎么利用Advisor建立Callback数组的

private Callback[] getCallbacks(Class<?> rootClass) throws Exception {// 取ProxyFactory的属性boolean exposeProxy = this.advised.isExposeProxy();boolean isFrozen = this.advised.isFrozen();boolean isStatic = this.advised.getTargetSource().isStatic();// Choose an "aop" interceptor (used for AOP calls).Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);Callback targetInterceptor;if (exposeProxy) {targetInterceptor = (isStatic ?new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));}else {targetInterceptor = (isStatic ?new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));}// Choose a "direct to target" dispatcher (used for// unadvised calls to static targets that cannot return this).Callback targetDispatcher = (isStatic ?new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());Callback[] mainCallbacks = new Callback[] {aopInterceptor,  // for normal advice,执行Interceptor链targetInterceptor,  // invoke target without considering advice, if optimized 将代理对象设置到ThreadLocal中,AopContext.setCurrentProxy(proxy)new SerializableNoOp(),  // no override for methods mapped to thistargetDispatcher, this.advisedDispatcher,new EqualsInterceptor(this.advised),new HashCodeInterceptor(this.advised)};Callback[] callbacks;if (isStatic && isFrozen) {Method[] methods = rootClass.getMethods();Callback[] fixedCallbacks = new Callback[methods.length];this.fixedInterceptorMap = CollectionUtils.newHashMap(methods.length);// TODO: small memory optimization here (can skip creation for methods with no advice)for (int x = 0; x < methods.length; x++) {Method method = methods[x];List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());this.fixedInterceptorMap.put(method, x);}// Now copy both the callbacks from mainCallbacks// and fixedCallbacks into the callbacks array.callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);this.fixedInterceptorOffset = mainCallbacks.length;}else {callbacks = mainCallbacks;}return callbacks;}

关键是这句代码Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);。这句代码就创建了一个DynamicAdvisedInterceptor对象,在使用cglib时这个callbacks数组里面存的对象其实就是MethodInterceptor,而这个类就是MethodInterceptor的子类。然后会调用intercept方法来执行代理逻辑。我们关键看这个intercept方法。

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动态代理都在做一件事,观察当前的advisor的exposeProxy是否为true,如果是就设置到ThreadLocal中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);//和jdk一样这里同样是获得一个Advisor执行链List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);Object retVal;if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = methodProxy.invoke(target, argsToUse);}else {//然后执行proceed方法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);}}}

分析上面代码我们可以看出,它这里的逻辑其实和jdk动态代理的invoke逻辑是一样的。这里就不详细分析了。

经过前面的分析我们知道了ProxyFactory底层是如何利用jdk和Cglib生成代理对象,以及执行代理逻辑的。现在我们把视角放大,上面讲的东西和Spring AOP有什么关系呢?下面我们就开始分析Spring AOP源码。

三、 Spring AOP源码分析

首先经过前面的分析,我们知道AOP发生的过程是在bean的生命周期的初始化之后(这里不考虑循环依赖中提前AOP的情况)。所以我们进入doCreateBean方法。

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {
......
try {// 属性填充populateBean(beanName, mbd, instanceWrapper);// 初始化exposedObject = initializeBean(beanName, exposedObject, mbd);}......
}

exposedObject = initializeBean(beanName, exposedObject, mbd);这个就是执行Bean的初始化,我们进入initializeBean方法。

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {//执行回调方法invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;// 初始化前if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}// 初始化try {invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}// 初始化后 AOPif (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;}

注意上面代码就是一个Bean初始化后要做的事情,关于AOP这块就是在下面这段代码中:

// 初始化后 AOPif (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}@Overridepublic Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {//拿到当前的beanObject result = existingBean;//获取所有的BeanPostProcessorfor (BeanPostProcessor processor : getBeanPostProcessors()) {//执行BeanPostProcessor的postProcessAfterInitializationObject current = processor.postProcessAfterInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;}

applyBeanPostProcessorsAfterInitialization方法的逻辑就是,找到所有的BeanPostProcessor然后执行每个BeanPostProcessor的postProcessAfterInitialization方法来执行初始化后的逻辑。这里我们先要知道AOP就是需要一个特定的BeanPostProcessor去执行它的postProcessAfterInitialization方法来实现AOP的。下面我们就来揭开这个特殊的BeanPostProcessor的面纱。

首先我们知道,要开启AOP我们需要在配置类上加入@EnableAspectJAutoProxy注解。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {boolean proxyTargetClass() default false;boolean exposeProxy() default false;
}
  • proxyTargetClass(): 默认值为 false,表示是否强制使用CGLIB代理方式。如果设置为 true,则表示使用CGLIB代理;否则使用JDK动态代理。
  • exposeProxy(): 默认值为 false,表示是否将当前代理对象暴露为ThreadLocal。如果设置为 true,则可以通过AopContext.currentProxy()来获取当前代理对象。

注意这个注解上面导入了@Import(AspectJAutoProxyRegistrar.class)在分析Spring启动源码的时候,我们分析过这个注解的作用可以起一个导入Bean的作用。这也是EnableAspectJAutoProxy注解的核心作用。我们就来分析一下这个类。

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {// 注册一个AnnotationAwareAspectJAutoProxyCreator类型的Bean,beanName为AUTO_PROXY_CREATOR_BEAN_NAMEAopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);// 修改AnnotationAwareAspectJAutoProxyCreator中对应的属性AnnotationAttributes enableAspectJAutoProxy =AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);if (enableAspectJAutoProxy != null) {if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);}if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);}}}}

首先这个类实现了ImportBeanDefinitionRegistrar这个接口,所以这个类在Spring启动过程中会调用registerBeanDefinitions方法。方法里注册一个AnnotationAwareAspectJAutoProxyCreator类型的BeanDefinition,beanName为AUTO_PROXY_CREATOR_BEAN_NAME。这个Bean就是AOP的关键。

//1
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
//2
@Nullablepublic static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);}
//3
@Nullablepublic static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);}//4 
@Nullableprivate static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);if (!cls.getName().equals(apcDefinition.getBeanClassName())) {int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());int requiredPriority = findPriorityForClass(cls);if (currentPriority < requiredPriority) {apcDefinition.setBeanClassName(cls.getName());}}return null;}//这里就是注册前面bean得逻辑RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);beanDefinition.setSource(source);beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);return beanDefinition;}

下面我们就开始分析这个核心beanAUTO_PROXY_CREATOR_BEAN_NAME

public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {@Nullableprivate List<Pattern> includePatterns;@Nullableprivate AspectJAdvisorFactory aspectJAdvisorFactory;@Nullableprivate BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;public void setIncludePatterns(List<String> patterns) {this.includePatterns = new ArrayList<>(patterns.size());for (String patternText : patterns) {this.includePatterns.add(Pattern.compile(patternText));}}public void setAspectJAdvisorFactory(AspectJAdvisorFactory aspectJAdvisorFactory) {Assert.notNull(aspectJAdvisorFactory, "AspectJAdvisorFactory must not be null");this.aspectJAdvisorFactory = aspectJAdvisorFactory;}@Overrideprotected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {super.initBeanFactory(beanFactory);if (this.aspectJAdvisorFactory == null) {this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);}this.aspectJAdvisorsBuilder =new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);}@Overrideprotected List<Advisor> findCandidateAdvisors() {// Add all the Spring advisors found according to superclass rules.// 先找到所有Advisor类型的Bean对象List<Advisor> advisors = super.findCandidateAdvisors();// Build Advisors for all AspectJ aspects in the bean factory.// 再从所有切面中解析得到Advisor对象if (this.aspectJAdvisorsBuilder != null) {advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());}return advisors;}@Overrideprotected boolean isInfrastructureClass(Class<?> beanClass) {return (super.isInfrastructureClass(beanClass) ||(this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));}protected boolean isEligibleAspectBean(String beanName) {if (this.includePatterns == null) {return true;}else {for (Pattern pattern : this.includePatterns) {if (pattern.matcher(beanName).matches()) {return true;}}return false;}}private class BeanFactoryAspectJAdvisorsBuilderAdapter extends BeanFactoryAspectJAdvisorsBuilder {public BeanFactoryAspectJAdvisorsBuilderAdapter(ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {super(beanFactory, advisorFactory);}@Overrideprotected boolean isEligibleBean(String beanName) {return AnnotationAwareAspectJAutoProxyCreator.this.isEligibleAspectBean(beanName);}}}

我们从这个类开始不断找到它的父类,以及父类的父类,会来到这个类。

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupportimplements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {}

它实现了implements SmartInstantiationAwareBeanPostProcessor说明,上面注册的那个bean确实是一个BeanPostProcessor。好现在我们知道了这个BeanPostProcessor,现在我们继续回到Bean的生命周期中。

@Overridepublic Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {//拿到当前的beanObject result = existingBean;//获取所有的BeanPostProcessorfor (BeanPostProcessor processor : getBeanPostProcessors()) {//执行BeanPostProcessor的postProcessAfterInitializationObject current = processor.postProcessAfterInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;}

关键代码就是执行bject current = processor.postProcessAfterInitialization(result, beanName);。然后上面关于AOP的BeanPostProcessor就会执行下面代码

@Overridepublic Object postProcessAfterInstantiation(@Nullable Object bean, String beanName) {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (this.earlyProxyReferences.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;}// this.advisedBeans表示已经判断过了的bean,false表示此bean不需要进行Aop  if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}// 当前正在创建的Bean不用进行AOP,比如切面Bean,advisedBeans里面就存储了不需要进行AOP的beanif (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}// Create proxy if we have advice.// 判断当前bean是否存在匹配的advice,如果存在则要生成一个代理对象// 此处根据类以及类中的方法去匹配到Interceptor(也就是Advice),然后生成代理对象,代理对象在执行的时候,还会根据当前执行的方法去匹配Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);if (specificInterceptors != DO_NOT_PROXY) {// advisedBeans记录了某个Bean已经进行过AOP了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;}

上面方法首先会找出不需要进行AOP的bean,如我们的加了Aspectj注解的bean,并加入到this.advisedBeans这个集合中。我们重点看下面代码:

Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

其实上面的代码就是判断当前的bean需不需要进行AOP,相信大家还记得ProxyFactory的逻辑里面也进行了一次判断。如果要进行AOP,则进入的下面的if判断,否则这几返回bean。

if (specificInterceptors != DO_NOT_PROXY) {// advisedBeans记录了某个Bean已经进行过AOP了this.advisedBeans.put(cacheKey, Boolean.TRUE);Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}

上面调用了createProxy来创建代理对象,进入该方法。

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);}//创建一个ProxyFactoryProxyFactory proxyFactory = new ProxyFactory();proxyFactory.copyFrom(this);if (proxyFactory.isProxyTargetClass()) {// Explicit handling of JDK proxy targets (for introduction advice scenarios)if (Proxy.isProxyClass(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);// 在这一步会去判断advisors中是否存在IntroductionAdvisor,如果存在则会把对应的interface添加到proxyFactory中去proxyFactory.addAdvisors(advisors);//设置TargetproxyFactory.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 loaderClassLoader classLoader = getProxyClassLoader();if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();}return proxyFactory.getProxy(classLoader);}

看到上面代码我们就会到了ProxyFactory的逻辑,这里就将SpringAOP和ProxyFactory联系起来了,后面如何产生代理对象,前面都分析了。proxyFactory.addAdvisors(advisors);就是添加Advisor,那么这个Advisor哪里来,其实就是参数中的 Object[] specificInterceptors这个数组,这个数组是由前面调用的getAdvicesAndAdvisorsForBean方法来的,假如现在BeanPostProcessor处理的bean为Userservice,通过该方法就可以找到所有和UserService有关的Advisor,我们看看这个方法底层是如何找的。

@Override@Nullableprotected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {// 寻找匹配的AdvisorList<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);if (advisors.isEmpty()) {return DO_NOT_PROXY;}return advisors.toArray();}

findEligibleAdvisors这个是寻找匹配的Advisor的核心方法,我们进入该方法。

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {// 找到所有的AdvisorList<Advisor> candidateAdvisors = findCandidateAdvisors();// 进行筛选List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);extendAdvisors(eligibleAdvisors);// 对Advisor进行排序,按Ordered接口、@Order注解进行排序if (!eligibleAdvisors.isEmpty()) {eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;}

List<Advisor> candidateAdvisors = findCandidateAdvisors();就会找到所有的Advisor。

	@Overrideprotected List<Advisor> findCandidateAdvisors() {// Add all the Spring advisors found according to superclass rules.// 先找到所有Advisor类型的Bean对象List<Advisor> advisors = super.findCandidateAdvisors();// Build Advisors for all AspectJ aspects in the bean factory.// 再从所有切面中解析得到Advisor对象if (this.aspectJAdvisorsBuilder != null) {advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());}return advisors;}

上面代码首先调用super.findCandidateAdvisors找到所有Advisor类型的bean,然后解析加了@AspectJ注解的bean解析出来。

public List<Advisor> buildAspectJAdvisors() {// aspectBeanNames是用来缓存BeanFactory中所存在的切面beanName的,第一次为null,后面就不为null了,不为null表示之前就已经找到过BeanFactory中的切面了List<String> aspectNames = this.aspectBeanNames;if (aspectNames == null) {synchronized (this) {aspectNames = this.aspectBeanNames;if (aspectNames == null) {List<Advisor> advisors = new ArrayList<>();aspectNames = new ArrayList<>();// 把所有beanNames拿出来遍历,判断某个bean的类型是否是AspectString[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);for (String beanName : beanNames) {if (!isEligibleBean(beanName)) {continue;}//获取当前bean的类型Class<?> beanType = this.beanFactory.getType(beanName, false);if (beanType == null) {continue;}//判断当前类型bean上面是否有AspectJ注解if (this.advisorFactory.isAspect(beanType)) {aspectNames.add(beanName);// 切面的注解信息AspectMetadata amd = new AspectMetadata(beanType, beanName);// 如果@Aspect不是perthis、pertarget,那么一个切面只会生成一个对象(单例)// 并且会将该切面中所对应的Advisor对象进行缓存if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {MetadataAwareAspectInstanceFactory factory =new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);// 利用BeanFactoryAspectInstanceFactory来解析Aspect类List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);if (this.beanFactory.isSingleton(beanName)) {// 缓存切面所对应的所有Advisor对象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);// 利用PrototypeAspectInstanceFactory来解析Aspect类// PrototypeAspectInstanceFactory的父类为BeanFactoryAspectInstanceFactory// 这两个Factory的区别在于PrototypeAspectInstanceFactory的构造方法中会判断切面Bean是不是原型,除此之外没有其他区别// 所以主要就是BeanFactoryAspectInstanceFactory来负责生成切面实例对象advisors.addAll(this.advisorFactory.getAdvisors(factory));}}}this.aspectBeanNames = aspectNames;return advisors;}}}if (aspectNames.isEmpty()) {return Collections.emptyList();}// 如果切面已经找到过了,那么则遍历每个切面是否缓存了对应的Advisor,如果没有缓存则进行解析得到AdvisorList<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;}

上面的类就是解析加了@Aspectj注解的bean,其实就是解析里面的@Before等注解,然后生成一系列的Advisor对象返回,底层还是很复杂的,这里就不深入分析了。回到wrapIfNecessary,现在就找到了很多Advisor。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/240454.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

工业平板定制方案_基于联发科、紫光展锐平台的工业平板电脑方案

工业平板主板采用联发科MT6762平台方案&#xff0c;搭载Android 11.0操作系统&#xff0c; 主频最高2.0GHz&#xff0c;效能有大幅提升;采用12nm先进工艺&#xff0c;具有低功耗高性能的特点。 该工业平板主板搭载了IMG GE8320图形处理器&#xff0c;最高主频为680MHz, 支持108…

通过wireshark抓取的流量还原文件(以zip为例)

wireshark打开流量包&#xff0c;通过zip关键字查找 追踪流可查看详细信息 选中media Type右键&#xff0c; 点击导出分组字节流选项 将生成的文件进行命名&#xff0c;需要时什么格式就以什么格式后缀

DQN、Double DQN、Dueling DQN、Per DQN、NoisyDQN 学习笔记

文章目录 DQN (Deep Q-Network)说明伪代码应用范围 Double DQN说明伪代码应用范围 Dueling DQN实现原理应用范围伪代码 Per DQN (Prioritized Experience Replay DQN)应用范围伪代码 NoisyDQN伪代码应用范围 部分内容与图片摘自&#xff1a;JoyRL 、 EasyRL DQN (Deep Q-Networ…

Kafka-消费者-KafkaConsumer分析-ConsumerCoordinator

在前面介绍了Kafka中Rebalance操作的相关方案和原理。 在KafkaConsumer中通过ConsumerCoordinator组件实现与服务端的GroupCoordinator的交互&#xff0c;ConsumerCoordinator继承了AbstractCoordinator抽象类。 下面我们先来介绍AbstractCoordinator的核心字段&#xff0c;如…

UML-活动图

提示&#xff1a;大家可以参考我的状态图博客 UML-活动图 一、活动图的基本概念1.开始状态和结束状态2.动作状态和活动状态&#xff08;活动&#xff09;3.分支与合并4.分叉与合并5.活动转换&#xff08;1&#xff09;转移&#xff08;2&#xff09;判定 6.泳道 二、活动图的例…

数据结构:顺序栈

栈是一种先进后出的数据结构&#xff0c;只允许在一端&#xff08;栈顶&#xff09;操作&#xff0c;代码中top表示栈顶。 stack.h /* * 文件名称&#xff1a;stack.h * 创 建 者&#xff1a;cxy * 创建日期&#xff1a;2024年01月17日 * 描 述&#xff1a; …

数据分片概述、环境准备、部署MyCAT服务、全局表、分片表、ER表

1 案例1&#xff1a;部署mycat服务 1.1 问题 把主机mysql60 配置为 MySQL59 的从服务器把主机mysql62 配置为 MySQL61 的从服务器把主机mycat63 配置为mycat服务器客户端192.168.88.50访问mycat服务 1.2 方案 准备6台虚拟机&#xff0c;具体配置如表-1 1.3 步骤 实现此案例…

Docker中创建并配置MySQL、nginx、redis等容器

Docker中安装并配置MySQL、nginx、redis等 文章目录 Docker中安装并配置MySQL、nginx、redis等一、创建nginx容器①&#xff1a;拉取镜像②&#xff1a;运行nginx镜像③&#xff1a;从nginx容器中映射nginx配置文件到本地④&#xff1a;重启nginx并重新配置nginx的挂载 二、创建…

React全局状态管理

redux是一个状态管理框架&#xff0c;它可以帮助我们清晰定义state和处理函数&#xff0c;提高可读性&#xff0c;并且redux中的状态是全局共享&#xff0c;规避组件间通过props传递状态等操作。 快速使用 在React应用的根节点&#xff0c;需要借助React的Context机制存放整个…

新定义51单片机(RD8G37)实现测距测速仪

本文描述用新定义51单片机&#xff08;RD8G37&#xff09;超声波一体测距传感器实现简单的测距测速仪。 测距仪演示效果 新定义RD8G37Q48RJ开发板 超声波测距模块&#xff1a; 8位并口屏 1、main.c unsigned short timeConsuming0; unsigned int oldDistance;void rectClearS…

jeecgboot 前端bug or 后端 看图

无法显示文本 只能显示value 很恶心 如果用 varchar 就可以 不知道有没有别的方式 用int 解决 ,可能是我没有发现好的方法

Peter算法小课堂—并查集

我们先来看太戈编程467题 攀亲戚 题目描述&#xff1a; 最近你发现自己和古代一个皇帝长得很像&#xff1a;都有两个鼻子一个眼睛&#xff0c;你想知道这皇帝是不是你的远方亲戚&#xff0c;你是不是皇亲国戚。目前你能掌握的信息有m条&#xff0c;关于n个人&#xff1a;第i条…

手机崩溃日志的查找与分析

手机崩溃日志的查找与分析 摘要 本文介绍了一款名为克魔助手的iOS应用日志查看工具&#xff0c;该工具可以方便地查看iPhone设备上应用和系统运行时的实时日志和崩溃日志。同时还提供了崩溃日志的分析查看模块&#xff0c;可以对苹果崩溃日志进行符号化、格式化和分析&#x…

yolov5训练自己的数据

目录 1. 环境搭建2. 数据准备3. 数据标注4. 数据整理4.1 数据集切分4.2 修改数据文件4.3 修改模型文件 5. 训练模型5.1 训练5.2 验证5.3 测试 6. 训练结果分析 1. 环境搭建 安装anaconda、python、 cuda、 cudnn、 pytoch、 torchvision、 torchaudio等等。这里不详述 2. 数据…

软件测试大作业||测试计划+测试用例+性能用例+自动化用例+测试报告

xxx学院 2023—2024 学年度第二学期期末考试 《软件测试》&#xff08;A&#xff09;试题&#xff08;开卷&#xff09; 题目&#xff1a;以某一 web 系统为测试对象&#xff0c;完成以下文档的编写&#xff1a; &#xff08;满分 100 分&#xff09; &#xff08;1&am…

量化研究员!你应该如何写一手好代码

即使是Quant Researcher&#xff0c; 写一手高质量的代码也是非常重要的。再好的思路&#xff0c;如果不能正确地实现&#xff0c;都是没有意义的。 写一手高质量的代码的意义&#xff0c;对Quant developer来讲就更是自不待言了。这篇笔记就介绍一些python best practice。 始…

QT第二周周三

题目&#xff1a;使用图片绘制出仪表盘 代码&#xff1a; widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *paren…

申请开启|成为亚马逊云科技 Community Builder,共建云端社区!

在探索由技术打造的云端世界时&#xff0c;和同行者一起学习&#xff0c;与技术专家共同探讨是开发者成长的最佳助力&#xff01; 亚马逊云科技开发者社区 Community Builders 为技术爱好者和新兴思想领袖提供技术资源、学习和交流机会&#xff0c;帮助开发者探索、分享技术相关…

【车载HMI开发工具--EB GUIDE 与 Unity 合作提供一体化的沉浸式 HMI 设计开发工具链】【转载】

随着车载高性能计算平台的日益普及以及显示器尺寸和数量的不断增加&#xff0c;沉浸式车载人机交互界面&#xff08;HMI&#xff09;的需求也在持续增长。为了将实时 3D 技术带入车载 HMI 领域&#xff0c;Unity 与 Elektrobit (EB)展开了合作&#xff0c;EB 是推进 HMI 功能安…

CC工具箱使用指南:【添加字段(批量)】

一、简介 Arcgis中添加字段是常用的一个操作&#xff0c;软件中也自带有添加字段工具。 如果要给一个要素或表批量添加字段&#xff0c;可以用迭代器或批处理。 但如果理复杂一点&#xff0c;有多个GDB要素、表格&#xff0c;或者是SHP文件&#xff0c;需要给这个要素或表添…