Spring AOP 解析

本文详细介绍了Spring框架中的ProxyFactory如何创建JDK动态代理和CGLIB动态代理,展示了ProxyFactory的使用示例,以及代理对象的创建和执行过程,包括AOP的代理机制和Spring与生命周期的关联。
摘要由CSDN通过智能技术生成

Spring AOP 解析

ProxyFactory 解析

ProxyFactory 是 Spring 框架提供的一个代理工厂类,通过简化代理对象的创建过程,提供了一种方便的方式来生成代理对象。
ProxyFactory可以用于创建两种类型的代理对象:JDK动态代理和CGLIB动态代理。ProxyFactory根据所代理的目标对象的类型以及配置的代理类型,决定使用哪种动态代理方式来创建代理对象。

基本使用

/**
	定义一个需要被代理的类
*/
public class ProxyService {

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

    public static void main(String[] args) {
		// 创建需要被代理的对象
        ProxyService target = new ProxyService();
		
        ProxyFactory proxyFactory = new ProxyFactory();
        // 设置被代理的对象
        proxyFactory.setTarget(target);
        // 设置advice,定义aop的处理逻辑
        // 可以设置多个advice,会按照添加顺序,依次执行
        proxyFactory.addAdvice(new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation methodInvocation) throws Throwable {
                System.out.println("proxy before1 ...");
                Object proceed = methodInvocation.proceed();
                System.out.println("proxy after1 ...");
                return proceed;
            }
        });

        proxyFactory.addAdvice(new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation methodInvocation) throws Throwable {
                System.out.println("proxy before2 ...");
                Object proceed = methodInvocation.proceed();
                return proceed;
            }
        });
		
		// 通过proxyFactory获取代理对象,并执行代理方法
        ProxyService proxy = (ProxyService) proxyFactory.getProxy();
        proxy.proxyMethod1();

    }

原理分析

代理对象创建过程

在使用 ProxyFacory 创建代理对象时,Spring 会自己进行判断,是使用 JDK 动态代理还是 CGLIB 动态代理。

	/**
		判断是使用jdk动态代理还是cglib动态代理
	*/
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		// 是不是是否在GraalVM虚拟机上运行 && (isOptimize是否为true || isProxyTargetClass是否为true || 被代理对象是否实现接口)
		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 动态代理,然后去调用各自的 getProxy() 方法,去返回代理对象。

  • JdkDynamicAopProxy
/**
	构造动态代理所需参数
*/
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
	this.advised = config;
	// 设置JDK动态代理所要代理的接口
	// 将SpringProxy、Advised、DecoratingProxy三个接口,组合成一个Class[],赋值给proxiedInterfaces
	this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
	// 检查这些接口中是否定义了equals()、hashcode()方法
	findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
}

public Object getProxy(@Nullable ClassLoader classLoader) {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
	}
	// 此处的proxiedInterfaces是在上面的构造方法中进行赋值的
	// 创建代理对象,并返回
	return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
  • ObjenesisCglibAopProxy
public 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);
				}
			}

			// 验证代理类是否可用。			
			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));

			// 获取和被代理类所匹配的Advisor
			Callback[] callbacks = getCallbacks(rootClass);
			Class<?>[] types = new Class<?>[callbacks.length];
			for (int x = 0; x < types.length; x++) {
				types[x] = callbacks[x].getClass();
			}
			// 创建回调过滤器
			enhancer.setCallbackFilter(new ProxyCallbackFilter(
					this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
			enhancer.setCallbackTypes(types);

			// 返回代理对象
			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() failed
			throw new AopConfigException("Unexpected AOP exception", ex);
		}
	}

上述逻辑总结为:

  1. 创建Enhancer对象
  2. 设置Enhancer的superClass为通过ProxyFactory.setTarget()所设置的对象的类
  3. 设置Enhancer的interfaces为通过ProxyFactory.addInterface()所添加的接口,以及SpringProxy、Advised、DecoratingProxy接口
  4. 设置Enhancer的Callbacks为DynamicAdvisedInterceptor
  5. 最后创建一个代理对象,代理对象在执行某个方法时,会进入到DynamicAdvisedInterceptor的intercept()方法中
代理对象执行过程
	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 {
			// 如果接口中没有定义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)) {
				// hashCode方法同理
				return hashCode();
			}
			else if (method.getDeclaringClass() == DecoratingProxy.class) {
				// 得到代理对象的类型,而不是所实现的接口
				return AopProxyUtils.ultimateTargetClass(this.advised);
			}
			else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				// 也是直接调用Advised接口中的方法,不走代理逻辑
				// 其实就是利用代理对象获取ProxyFactory中的信息
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;

			// 如果ProxyFactory的exposeProxy为true,则将代理对象设置到currentProxy这个ThreadLocal中去
			if (this.advised.exposeProxy) {
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			// 被代理对象和代理类
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			// 代理对象在执行某个方法时,根据方法筛选出匹配的Advisor,并适配成Interceptor
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
			
			if (chain.isEmpty()) {
				// 如果没有Advice,则直接调用对应方法
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				// advisor不为空,按照链进行依次执行
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, 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())) {
		
				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);
			}
		}
	}
	

其中,筛选 advisor 的方法如下:经过类、方法等一系列匹配,将和方法所匹配的Advisor适配成MethodInterceptor,并返回

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
			Advised config, Method method, @Nullable Class<?> targetClass) {
		
		AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
		// 从ProxyFactory中拿到所设置的Advice(添加时被封装成了DefaultPointcutAdvisor)
		// 添加的时候会控制顺序
		Advisor[] advisors = config.getAdvisors();
		List<Object> interceptorList = new ArrayList<>(advisors.length);
		Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
		Boolean hasIntroductions = null;

		for (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,也是ThrowsAdvice
						MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
						if (mm.isRuntime()) {
							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封装成为Interceptor
				Interceptor[] interceptors = registry.getInterceptors(advisor);
				interceptorList.addAll(Arrays.asList(interceptors));
			}
		}

		return interceptorList;
	}

proceed() 方法执行流程如下:使用到了责任链模式,对每个代理逻辑进行顺序调用

public Object proceed() throws Throwable {

		// currentInterceptorIndex初始值为-1,每调用一个interceptor就会加1
		// 当调用完了最后一个interceptor后就会执行被代理方法
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}

		// currentInterceptorIndex初始值为-1
		Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

		// 当前interceptor是InterceptorAndDynamicMethodMatcher,则先进行匹配,匹配成功后再调用该interceptor
		// 如果没有匹配则递归调用proceed()方法,调用下一个interceptor
		if (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 {
				// 不匹配则执行下一个MethodInterceptor
				return proceed();
			}
		}
		else {			
			// 直接调用MethodInterceptor,传入this,在内部会再次调用proceed()方法进行递归
			// 比如MethodBeforeAdviceInterceptor
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

上述方法的流程主要是:

  1. 在使用ProxyFactory创建代理对象之前,需要往ProxyFactory先添加Advisor
  2. 代理对象在执行某个方法时,会把ProxyFactory中的Advisor拿出来和当前正在执行的方法进行匹配筛选
  3. 把和方法所匹配的Advisor适配成MethodInterceptor
  4. 把和当前方法匹配的MethodInterceptor链,以及被代理对象、代理对象、代理类、当前Method对象、方法参数封装为MethodInvocation对象
  5. 调用MethodInvocation的proceed()方法,开始执行各个MethodInterceptor以及被代理对象的对应方法
  6. 按顺序调用每个MethodInterceptor的invoke()方法,并且会把MethodInvocation对象传入invoke()方法
  7. 直到执行完最后一个MethodInterceptor了,就会调用invokeJoinpoint()方法,从而执行被代理对象的当前方法

ProxyFactory 与 Spring 生命周期的关系

在 Spring 中,开启 AOP 需要添加 @EnableAspectJAutoProxy 注解,该注解会往 Spring 容器中,注册一个 AbstractAdvisorAutoProxyCreator 类型的 Bean,该类又实现了 BeanPostProcessor接口,所以在生命周期中,就会调用该类的方法,进行 AOP,也就是开启了 Spring 的 AOP 功能。
在 Spring 生命周期的初始化后方法中,会掉用 wrapIfNecessary()方法,在该方法中,判断是否需要进行代理。

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}

		// advisedBeans表示已经判断过了的bean,false表示此bean不需要进行Aop
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}

		// 当前正在创建的Bean不用进行AOP,比如切面Bean
		if (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);
			// 在该方法中,使用proxyFactory进行代理对象的创建,并返回
			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;
	}

在某个Bean初始化之后,会调用 wrapIfNecessary() 方法进行AOP,底层逻辑是,AbstractAdvisorAutoProxyCreator会找到所有的 Advisor,然后判断当前这个 Bean 是否存在某个 Advisor 与之匹配(根据Pointcut),如果匹配就表示当前这个 Bean 有对应的切面逻辑,需要进行 AOP,需要产生一个代理对象。

  • 24
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值