spring aop 初探

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary

分析JDK动态代理

生成的代理对象  构造函数,入参为 InvocationHandler

public com.sun.proxy.$Proxy164(java.lang.reflect.InvocationHandler)

生成动态代理Class对象:

Class<?> cl = getProxyClass0(loader, intfs);

实例化动态代理对象:

final Constructor<?> cons = cl.getConstructor({ InvocationHandler.class });

cons.newInstance(new Object[]{h});

方法

equals,toString,hashCode 

0 = {Method@10598} "public final boolean com.sun.proxy.$Proxy164.equals(java.lang.Object)"
1 = {Method@10599} "public final java.lang.String com.sun.proxy.$Proxy164.toString()"
2 = {Method@10600} "public final int com.sun.proxy.$Proxy164.hashCode()"

和 所有代理接口中的 所有方法。

代理对象的方法实现逻辑:比如 equals方法

return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();

就是调用 

java.lang.reflect.InvocationHandler#invoke

public interface InvocationHandler {

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;

}

 第一个参数,代理对象本身

第二个参数,调用的代理的接口中的方法

第三个参数,调用的方法 入参

JDK动态代理 需要开发者关注的,就是 实现 InvocationHandler 接口。实际 也并不需要很复杂的实现,可以引用另一个服务来实现。

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator

在spring 实例化 bean之后,会执行

public Object postProcessAfterInitialization(@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;
	}

完成aop 代理对象的生成。

JDK动态代理的 InvocationHandler 的实现类为 JdkDynamicAopProxy,其增强功能由 advised 完成。和上面画的结构 基本一致。

Advisor

寻找Advisor

// org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
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;
	}

第一部分,直接查找所有的 Advisor类型的bean

this.beanFactory.getBean(name, Advisor.class)

第二部分,查询标有 @Aspect 注解的 bean

private boolean hasAspectAnnotation(Class<?> clazz) {
		return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
	}

 针对每个bean,找到所有 没有标记 @Pointcut 注解的方法

对每个方法查找对应的切面,标记 标记 @Around等注解的方法

private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
			Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};

protected enum AspectJAnnotationType {

		AtPointcut, AtAround, AtBefore, AtAfter, AtAfterReturning, AtAfterThrowing
}

获取 注解的value值,通常返回的是 标记有 @Pointcut 注解的 方法名

Method method = annotation.annotationType().getDeclaredMethod(attributeName);
ReflectionUtils.makeAccessible(method);
return method.invoke(annotation);

开始包装该切面方法:

关键代码块

switch (aspectJAnnotation.getAnnotationType()) {
			case AtPointcut:
				if (logger.isDebugEnabled()) {
					logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
				}
				return null;
			case AtAround:
				springAdvice = new AspectJAroundAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtBefore:
				springAdvice = new AspectJMethodBeforeAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfter:
				springAdvice = new AspectJAfterAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfterReturning:
				springAdvice = new AspectJAfterReturningAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterReturningAnnotation.returning())) {
					springAdvice.setReturningName(afterReturningAnnotation.returning());
				}
				break;
			case AtAfterThrowing:
				springAdvice = new AspectJAfterThrowingAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
					springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
				}
				break;
			default:
				throw new UnsupportedOperationException(
						"Unsupported advice type on method: " + candidateAdviceMethod);
		}

根据切面的类型,返回不同的Advice类型的对象。

org.springframework.aop.aspectj.AbstractAspectJAdvice

再包装成Advisor

org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl

寻找可以应用在当前bean的 advisor。这个逻辑有点复杂,先跳过

return canApply(pca.getPointcut(), targetClass, hasIntroductions);

接下来就是创建代理对象

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

		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		if (!proxyFactory.isProxyTargetClass()) {
			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);
		}

		return proxyFactory.getProxy(getProxyClassLoader());
	}

evaluateProxyInterfaces(beanClass, proxyFactory);

这里会提取 目前代理对象的 接口

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

将 接口 转为 Advisor 类型

1. 如果是 Advisor 直接返回

if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}

2. MethodInterceptor

if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}

3. 其他类型

MethodBeforeAdvice  MethodBeforeAdviceAdapter

AfterReturningAdvice  AfterReturningAdviceAdapter

ThrowsAdvice ThrowsAdviceAdapter

for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}

这里由个疑问,上述都是找的 Advisor 类型,为什么还有 不是Advisor的?

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)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

这边代码看起来绕来绕去,实际设计的比较精炼。使用一个工厂类的一个方法就返回了代理对象。

proxyFactory.getProxy(getProxyClassLoader());

createAopProxy().getProxy(classLoader)

getAopProxyFactory().createAopProxy(this)

多个方法级联调用,只是这里进行了 一个拆分。

public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
		Assert.notNull(config, "AdvisedSupport must not be null");
		if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
			throw new AopConfigException("No advisors and no TargetSource specified");
		}
		this.advised = config;
	}

上面描述了,JdkDynamicAopProxy就是 InvocationHandler的实现类。

Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);

这里会获取需要代理类实现的接口。然后使用JDK提供的代理生成方法获取代理示例 。

如果是 cglib完成代理生成,

enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));

其invoke方法内部 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 完了对切面的执行调用。

执行过程:

AspectJAroundAdvice

public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
return invokeAdviceMethod(pjp, jpm, null, null);
}

 

AspectJAfterAdvice

public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}

AspectJAfterReturningAdvice 由 AfterReturningAdviceInterceptor包装,

public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
invokeAdviceMethod(getJoinPointMatch(), returnValue, null);
return retVal;
}

AspectJAfterThrowingAdvice

public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}

AspectJMethodBeforeAdvice,由MethodBeforeAdviceInterceptor包装

public Object invoke(MethodInvocation mi) throws Throwable {
invokeAdviceMethod(getJoinPointMatch(), null, null);
return mi.proceed();
}

invokeAdviceMethod 方法就是调用 切面方法

mi.proceed()  就是执行下一个切面方法

第一个问题,advice的执行顺序是什么?

     每个advice 需要实现 org.springframework.core.Ordered接口,用于指定排序

第二个问题,什么时候执行业务方法?

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

protected Object invokeJoinpoint() throws Throwable {
     return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}

当所有Advice都调用后,会执行业务方法。

相关推荐

  1. SpringAOP的实现原理

    2024-07-18 00:22:03       48 阅读
  2. 一个简易的SpringAOP实例

    2024-07-18 00:22:03       53 阅读
  3. 浅谈SpringAOP实现原理

    2024-07-18 00:22:03       40 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-18 00:22:03       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-18 00:22:03       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-18 00:22:03       58 阅读
  4. Python语言-面向对象

    2024-07-18 00:22:03       69 阅读

热门阅读

  1. golang项目中gorm框架的配置和具体使用

    2024-07-18 00:22:03       21 阅读
  2. 使用Django框架实现音频上传功能

    2024-07-18 00:22:03       21 阅读
  3. 38 IRF+链路聚合+ACL+NAT组网架构

    2024-07-18 00:22:03       21 阅读
  4. Resilience4j 实现接口限流

    2024-07-18 00:22:03       22 阅读
  5. ld,GNU 链接器介绍以及命令行参数详解

    2024-07-18 00:22:03       17 阅读
  6. Windows 点云生成二维栅格图 [附C++完整代码实现]

    2024-07-18 00:22:03       19 阅读
  7. go recover

    2024-07-18 00:22:03       23 阅读
  8. docker从0到1 部署gitlab 纯干货

    2024-07-18 00:22:03       22 阅读
  9. C# —— var

    2024-07-18 00:22:03       23 阅读
  10. 【VUE】10、VUE项目中多环境管理使用

    2024-07-18 00:22:03       23 阅读