Spring AOP源码解析(中)

た 入场券 2023-10-01 09:27 140阅读 0赞

上一篇文章中,介绍了Spring中动态代理的使用方式,通过ProxyFactory来创建代理对象,ProxyFactory可以通过addAdvisor()来添加匹配逻辑和代理逻辑,这篇文章重点介绍ProxyFactory是如何产生代理对象以及代理对象是如何执行代理逻辑的

一、ProxyFactory生成代理对象

使用ProxyFactory添加advisor,并创建代理对象,调用代理对象的test()方法,代码如下:

BeforeAdvisor:

  1. public class LizhiBeforeAdvisor implements PointcutAdvisor {
  2. @Override
  3. public Advice getAdvice() {
  4. return new LizhiBeforeAdvice();
  5. }
  6. @Override
  7. public boolean isPerInstance() {
  8. return false;
  9. }
  10. @Override
  11. public Pointcut getPointcut() {
  12. return Pointcut.TRUE;
  13. }
  14. }
  15. public class LizhiBeforeAdvice implements MethodBeforeAdvice {
  16. @Override
  17. public void before(Method method, Object[] args, Object target) throws Throwable {
  18. System.out.println("before");
  19. }
  20. }

LizhiAroundAdvisorLizhiAfterReturningAdvisor与上面BeforeAdvisor逻辑基本类似

重点介绍getProxy()方法

  1. UserService target = new UserService();
  2. ProxyFactory proxyFactory = new ProxyFactory();
  3. proxyFactory.setTarget(target);
  4. proxyFactory.addAdvisor(new LizhiBeforeAdvisor());
  5. proxyFactory.addAdvisor(new LizhiAroundAdvisor());
  6. proxyFactory.addAdvisor(new LizhiAfterReturningAdvisor());
  7. UserService userService = (UserService) proxyFactory.getProxy();
  8. userService.test();
1.1 生成AopProxy

在生成代理对象之前,需要判断使用哪种代理方式来生成代理对象,JDK或CGLIB

  1. public Object getProxy() {
  2. return createAopProxy().getProxy();
  3. }
  4. protected final synchronized AopProxy createAopProxy() {
  5. if (!this.active) {
  6. activate();
  7. }
  8. // 默认为DefaultAopProxyFactory
  9. return getAopProxyFactory().createAopProxy(this);
  10. }

NativeDetector.inNativeImage()用于判断当前程序是否运行在GraalVM上(类似JVM),如果是着这种情况,就只能只用JDK动态代理

config对象就是ProxyFactory对象,isOptimize()判断是否需要进行优化,较早的版本,CGLIB的效率比JDK要好,可以通过设置ProxyFactory的optimize等于true来使用CGLIB

isProxyTargetClass()判断是否为类进行代理,如果为true,即使被代理类实现了接口,也会使用CGLIB进行代理

hasNoUserSuppliedProxyInterfaces()用于判断是否添加了接口,如果没有添加接口,则使用CGLIB

只满足上面这些条件,还不能直接使用CGLIB,还需要判断被代理的类是否为接口,如果是接口,则使用JDK动态代理;或者被代理类本身就是一个JDK代理类,也将使用JDK动态代理;

只有不满足上前上个条件时,才会使用CGLIB进行代理;其他情况都使用JDK进行动态代理

  1. public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
  2. if (!NativeDetector.inNativeImage() &&
  3. (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
  4. Class<?> targetClass = config.getTargetClass();
  5. if (targetClass == null) {
  6. throw new AopConfigException("TargetSource cannot determine target class: " +
  7. "Either an interface or a target is required for proxy creation.");
  8. }
  9. if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
  10. return new JdkDynamicAopProxy(config);
  11. }
  12. return new ObjenesisCglibAopProxy(config);
  13. }
  14. else {
  15. return new JdkDynamicAopProxy(config);
  16. }
  17. }
1.2 生成代理对象

生成AopProxy后就可以去生成代理对象了

JDK生成代理对象:

  1. public Object getProxy(@Nullable ClassLoader classLoader) {
  2. if (logger.isTraceEnabled()) {
  3. logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
  4. }
  5. // this实现了InvocationHandler
  6. return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
  7. }

CGLIB生成代理对象:

主要通过Enhancer来生成被代理类的代理类和代理对象,与JDK不同的点就在于不仅会生成一个代理对象,还会生成一个代理类

  1. // 被代理的类
  2. Class<?> rootClass = this.advised.getTargetClass();
  3. Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
  4. Class<?> proxySuperClass = rootClass;
  5. // 如果被代理类本身就已经是Cglib所生成的代理类了
  6. if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
  7. // 获取真正的被代理类
  8. proxySuperClass = rootClass.getSuperclass();
  9. // 获取被代理类所实现的接口
  10. Class<?>[] additionalInterfaces = rootClass.getInterfaces();
  11. for (Class<?> additionalInterface : additionalInterfaces) {
  12. this.advised.addInterface(additionalInterface);
  13. }
  14. }
  15. // Validate the class, writing log messages as necessary.
  16. validateClassIfNecessary(proxySuperClass, classLoader);
  17. // Configure CGLIB Enhancer...
  18. Enhancer enhancer = createEnhancer();
  19. if (classLoader != null) {
  20. enhancer.setClassLoader(classLoader);
  21. if (classLoader instanceof SmartClassLoader &&
  22. ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
  23. enhancer.setUseCache(false);
  24. }
  25. }
  26. // 被代理类,代理类的父类
  27. enhancer.setSuperclass(proxySuperClass);
  28. // 代理类额外要实现的接口
  29. enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
  30. enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
  31. enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
  32. // 获取和被代理类所匹配的Advisor
  33. Callback[] callbacks = getCallbacks(rootClass);
  34. Class<?>[] types = new Class<?>[callbacks.length];
  35. for (int x = 0; x < types.length; x++) {
  36. types[x] = callbacks[x].getClass();
  37. }
  38. // fixedInterceptorMap only populated at this point, after getCallbacks call above
  39. enhancer.setCallbackFilter(new ProxyCallbackFilter(
  40. this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
  41. enhancer.setCallbackTypes(types);
  42. // Generate the proxy class and create a proxy instance.
  43. return createProxyClassAndInstance(enhancer, callbacks);

二、执行代理逻辑

以JDK动态代理为例:

在调用代理对象的方法时,会进入到InvocationHandler的invoke()方法,而JdkDynamicAopProxy本身实现了InvocationHandler接口

2.1 不执行代理逻辑

如果接口中没有定义equals()和hashCode(),但代理对象调用了这两个方法,就直接执行这个方法,不执行代理逻辑

  1. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  2. Object oldProxy = null;
  3. boolean setProxyContext = false;
  4. // 拿到备代理对象
  5. TargetSource targetSource = this.advised.targetSource;
  6. Object target = null;
  7. // 如果接口中没有定义equals()方法,那么则直接调用,不走代理
  8. if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
  9. // The target does not implement the equals(Object) method itself.
  10. return equals(args[0]);
  11. }
  12. else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
  13. // The target does not implement the hashCode() method itself.
  14. return hashCode();
  15. }
  16. ……
  17. }
2.2 ThreadLocal设置代理对象

如果ProxyFactory的exposeProxy为true,则把当前的代理对象设置到当前线程的ThreadLocal中,业务代码中可以通过AopContext.currentProxy()获取到当前类的代理对象,可以用于解决事务方法调用时事务失效的问题

  1. private static final ThreadLocal<Object> currentProxy = new NamedThreadLocal<>("Current AOP proxy");
  2. if (this.advised.exposeProxy) {
  3. // Make invocation available if necessary.
  4. oldProxy = AopContext.setCurrentProxy(proxy);
  5. setProxyContext = true;
  6. }
  7. static Object setCurrentProxy(@Nullable Object proxy) {
  8. Object old = currentProxy.get();
  9. if (proxy != null) {
  10. currentProxy.set(proxy);
  11. }
  12. else {
  13. currentProxy.remove();
  14. }
  15. return old;
  16. }
2.3 获取所有匹配的Advice

通过getInterceptorsAndDynamicInterceptionAdvice()获取所有与当前类的当前方法匹配的Advice

  1. // 被代理对象和代理类
  2. target = targetSource.getTarget();
  3. Class<?> targetClass = (target != null ? target.getClass() : null);
  4. // Get the interception chain for this method.
  5. List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

先从缓存methodCache中去取,把method封装成MethodCacheKey,作为缓存的Key,如果缓存中没有,则通过getInterceptorsAndDynamicInterceptionAdvice()去获取

  1. public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
  2. MethodCacheKey cacheKey = new MethodCacheKey(method);
  3. // 注意这个List,表示的就是Advice链
  4. List<Object> cached = this.methodCache.get(cacheKey);
  5. if (cached == null) {
  6. cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
  7. this, method, targetClass);
  8. this.methodCache.put(cacheKey, cached);
  9. }
  10. return cached;
  11. }

ProxyFactory会把添加的advice都封装成advisor,然后遍历advisor进行匹配,主要通过Pointcut的逻辑进行匹配

  1. @Override
  2. public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
  3. Advised config, Method method, @Nullable Class<?> targetClass) {
  4. // This is somewhat tricky... We have to process introductions first,
  5. // but we need to preserve order in the ultimate list.
  6. AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
  7. // 从ProxyFactory中拿到所设置的Advice(添加时被封装成了DefaultPointcutAdvisor)
  8. // 添加的时候会控制顺序
  9. Advisor[] advisors = config.getAdvisors();
  10. List<Object> interceptorList = new ArrayList<>(advisors.length);
  11. Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
  12. Boolean hasIntroductions = null;
  13. ……
  14. return interceptorList;
  15. }

lizhiBeforeAdvisor:

  1. public class LizhiBeforeAdvisor implements PointcutAdvisor {
  2. @Override
  3. public Advice getAdvice() {
  4. return new LizhiBeforeAdvice();
  5. }
  6. @Override
  7. public boolean isPerInstance() {
  8. return false;
  9. }
  10. @Override
  11. public Pointcut getPointcut() {
  12. return new Pointcut() {
  13. @Override
  14. public ClassFilter getClassFilter() {
  15. return new ClassFilter() {
  16. @Override
  17. public boolean matches(Class<?> clazz) {
  18. return clazz.equals(UserService.class);
  19. }
  20. };
  21. }
  22. @Override
  23. public MethodMatcher getMethodMatcher() {
  24. return new MethodMatcher() {
  25. @Override
  26. public boolean matches(Method method, Class<?> targetClass) {
  27. return false;
  28. }
  29. @Override
  30. public boolean isRuntime() {
  31. return false;
  32. }
  33. @Override
  34. public boolean matches(Method method, Class<?> targetClass, Object... args) {
  35. return false;
  36. }
  37. };
  38. }
  39. };
  40. }
  41. }

遍历所有advisor进行匹配

根据上面定义的advisor,结合下面的匹配逻辑,可以清楚的看到,首先判断根据ClassFilter的matches()方法判断当前Advisor与当前类是否匹配,如果为true再进行方法匹配

先判断matches(Method method, Class<?> targetClass)是否匹配,如果为true,将Advisor封装成为MethodInterceptor,在真正执行Advisor的代理逻辑时,都是执行MethodInterceptor的invoke()方法里面的逻辑

再判断isRuntime()是否为true时,说明在调用方法时,还需要进行参数匹配,所以将isRuntime()为true的advisor封装成为InterceptorAndDynamicMethodMatcher,在真正调用时,还会调用matches(Method method, Class<?> targetClass, Object… args)方法进行校验

  1. for (Advisor advisor : advisors) {
  2. if (advisor instanceof PointcutAdvisor) {
  3. // Add it conditionally.
  4. PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
  5. // 先匹配类
  6. if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
  7. // 再匹配方法
  8. MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
  9. boolean match;
  10. if (mm instanceof IntroductionAwareMethodMatcher) {
  11. if (hasIntroductions == null) {
  12. hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
  13. }
  14. match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
  15. }
  16. else {
  17. match = mm.matches(method, actualClass);
  18. }
  19. if (match) {
  20. // 如果匹配则将Advisor封装成为Interceptor,当前Advisor中的Advice可能即是MethodBeforeAdvice,也是ThrowsAdvice
  21. MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
  22. if (mm.isRuntime()) {
  23. // Creating a new object instance in the getInterceptors() method
  24. // isn't a problem as we normally cache created chains.
  25. for (MethodInterceptor interceptor : interceptors) {
  26. interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
  27. }
  28. }
  29. else {
  30. interceptorList.addAll(Arrays.asList(interceptors));
  31. }
  32. }
  33. }
  34. }
  35. ……
  36. }
2.3.1 Advisor封装成MethodInterceptor
  1. MethodInterceptor[] interceptors = registry.getInterceptors(advisor);

如果Advice实现的是MethodInterceptor接口,则直接添加到interceptors

如果Advice是实现的Advice接口,则通过AdvisorAdapter进行适配,主要包括MethodBeforeAdviceAdapter、AfterReturningAdviceAdapter和ThrowsAdviceAdapter

  1. public DefaultAdvisorAdapterRegistry() {
  2. registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
  3. registerAdvisorAdapter(new AfterReturningAdviceAdapter());
  4. registerAdvisorAdapter(new ThrowsAdviceAdapter());
  5. }
  6. public void registerAdvisorAdapter(AdvisorAdapter adapter) {
  7. this.adapters.add(adapter);
  8. }
  9. public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
  10. List<MethodInterceptor> interceptors = new ArrayList<>(3);
  11. Advice advice = advisor.getAdvice();
  12. if (advice instanceof MethodInterceptor) {
  13. interceptors.add((MethodInterceptor) advice);
  14. }
  15. // 将Advice适配成MethodInterceptor
  16. for (AdvisorAdapter adapter : this.adapters) {
  17. if (adapter.supportsAdvice(advice)) {
  18. interceptors.add(adapter.getInterceptor(advisor));
  19. }
  20. }
  21. if (interceptors.isEmpty()) {
  22. throw new UnknownAdviceTypeException(advisor.getAdvice());
  23. }
  24. return interceptors.toArray(new MethodInterceptor[0]);
  25. }

通过AdvisorAdapter的supportsAdvice()方法进行适配,以MethodBeforeAdviceAdapter为例:

如果advice实现了MethodBeforeAdvice接口,返回true,然后调用getInterceptor()方法,将MethodBeforeAdvice封装成一个MethodBeforeAdviceInterceptor

  1. class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
  2. @Override
  3. public boolean supportsAdvice(Advice advice) {
  4. return (advice instanceof MethodBeforeAdvice);
  5. }
  6. @Override
  7. public MethodInterceptor getInterceptor(Advisor advisor) {
  8. MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
  9. return new MethodBeforeAdviceInterceptor(advice);
  10. }
  11. }
2.4 执行代理逻辑

当匹配所有的Advisor之后,没有像匹配的,则直接调用invokeJoinpointUsingReflection()方法

如果有相匹配的Advisor,则生成MethodInvocation对象,然后调用其proceed()方法

  1. List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
  2. // Check whether we have any advice. If we don't, we can fallback on direct
  3. // reflective invocation of the target, and avoid creating a MethodInvocation.
  4. if (chain.isEmpty()) {
  5. // We can skip creating a MethodInvocation: just invoke the target directly
  6. // Note that the final invoker must be an InvokerInterceptor so we know it does
  7. // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
  8. // 如果没有Advice,则直接调用对应方法
  9. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
  10. retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
  11. }
  12. else {
  13. // We need to create a method invocation...
  14. MethodInvocation invocation =
  15. new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
  16. // Proceed to the joinpoint through the interceptor chain.
  17. retVal = invocation.proceed();
  18. }

currentInterceptorIndex初始值为-1,每调用一个MethodInterceptor就会加1,按照Advisor添加的顺序,开始执行Advisor的代理逻辑

如果当前的MethodInterceptor为InterceptorAndDynamicMethodMatcher,需要调用matches(this.method, targetClass, this.arguments)进行参数匹配,匹配成功调用invoke()方法,匹配不成功,则递归调用,获取下一个MethodInterceptor,进行判断。

注意,invoke(this)的入参为当前类对象,会形成递归调用,相当于一条chain

  1. public Object proceed() throws Throwable {
  2. // We start with an index of -1 and increment early.
  3. // 当调用完了最后一个interceptor后就会执行被代理方法
  4. if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
  5. return invokeJoinpoint();
  6. }
  7. Object interceptorOrInterceptionAdvice =
  8. this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
  9. // 当前interceptor是InterceptorAndDynamicMethodMatcher,则先进行匹配,匹配成功后再调用该interceptor
  10. // 如果没有匹配则递归调用proceed()方法,调用下一个interceptor
  11. if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
  12. // Evaluate dynamic method matcher here: static part will already have
  13. // been evaluated and found to match.
  14. InterceptorAndDynamicMethodMatcher dm =
  15. (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
  16. Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
  17. // 动态匹配,根据方法参数匹配
  18. if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
  19. return dm.interceptor.invoke(this);
  20. }
  21. else {
  22. // Dynamic matching failed.
  23. // Skip this interceptor and invoke the next in the chain.
  24. // 不匹配则执行下一个MethodInterceptor
  25. return proceed();
  26. }
  27. }
  28. else {
  29. // It's an interceptor, so we just invoke it: The pointcut will have
  30. // been evaluated statically before this object was constructed.
  31. // 直接调用MethodInterceptor,传入this,在内部会再次调用proceed()方法进行递归
  32. // 比如MethodBeforeAdviceInterceptor
  33. return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
  34. }
  35. }

以MethodBeforeAdviceInterceptor为例:

调用MethodBeforeAdviceInterceptor的invoke()方法时,会先去执行before()方法的逻辑,然后再递归调用proceed()方法

  1. public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
  2. private final MethodBeforeAdvice advice;
  3. /**
  4. * Create a new MethodBeforeAdviceInterceptor for the given advice.
  5. * @param advice the MethodBeforeAdvice to wrap
  6. */
  7. public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
  8. Assert.notNull(advice, "Advice must not be null");
  9. this.advice = advice;
  10. }
  11. @Override
  12. @Nullable
  13. public Object invoke(MethodInvocation mi) throws Throwable {
  14. this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
  15. return mi.proceed();
  16. }
  17. }

在CGLIB中,执行逻辑同JDK,CGLIB是在DynamicAdvisedInterceptor的intercept()方法中去匹配Advisor,然后封装成CglibMethodInvocation,调用proceed()方法,CglibMethodInvocation实现了ReflectiveMethodInvocation,所以proceed()与JDK的proceed()是同一个方法

发表评论

表情:
评论列表 (有 0 条评论,140人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Spring AOP解析(上)

    一、动态代理 Spring AOP技术底层采用动态代理来实现,其中Java本身提供了JDK的动态,而Spring提供了CGLIB的的动态,下面简单介绍一下这种动态代理的使