欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 培训 > spring aop 初探

spring aop 初探

2024/10/24 4:47:51 来源:https://blog.csdn.net/htydowd/article/details/140035317  浏览:    关键词: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类型的对象。

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

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

 

接下来就是创建代理对象

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的实现类。

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

执行过程:

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com