- 1-Spring架构源码分析-Spring源码搭建
- 2-Spring架构源码分析-SSM框架说明
- 3-Spring架构源码分析-spring体系
- 4-Spring架构源码分析-Spring IOC机制设计思想和源码解读
- 5-Spring架构源码分析-Spring IOC之 Spring 统一资源加载策略
- 6-Spring架构源码分析-IoC 之加载 BeanDefinition
- 7-Spring架构源码分析-IoC 之注册 BeanDefinitions
- 8-Spring架构源码分析-IoC 之解析Bean:解析 import 标签
- 9-Spring架构源码分析-IoC 之解析 bean 标签:开启解析进程
- 10-Spring架构源码分析-IoC 之解析 bean标签:BeanDefinition
- 11-Spring架构源码分析-IoC 之注册解析的 BeanDefinitions
- 12-Spring架构源码分析-IoC 之装载 BeanDefinitions 总结
- 13-Spring架构源码分析-IoC 之开启 Bean 的加载
- 14-Spring架构源码分析-IoC 之加载 Bean:总结
- 15-Spring架构源码分析-Spring代理与AOP
- 16-Spring AOP源码分析-@EnableAspectJAutoProxy和AspectJAutoProxyRegistrar
- 17-Spring AOP源码分析-AnnotationAwareAspectJAutoProxyCreator
- 18-Spring AOP源码分析-AOP与BeanPostProcessor处理器
- 19-Spring AOP源码分析-代理对象调用目标方法
- 20-spring mvc设计思想和源码解读-spring mvc 功能特性
- 21-mvc 体系结构源码详解
- 22-Spring MVC源码跟踪
- 23-Spring事务源码分析
代理对象调用目标方法
背景知识:
@EnableAspectJAutoProxy(exposeProxy = true) 这个东东是用来干什么的?
没有配置exposeProxy 暴露代理对象的时候我们方法调用
我们在Mod方法中 通过this来调用本类的方法add()方法的时候,发现add()的方法不会被拦截
而我们配置了后exposeProxy的属性,我们发现可以通过
**int retVal = ((Calculate) AopContext.currentProxy()).add(numA,numB);
**
调用的时候,发现了add()方法可以被拦截
原理:把这个exposeProxy设置为true,会把代理对象存放在线程变量中,
AopContext.currentProxy())是从线程变量中获取代理对象(源码中分析)
应用场景(事物方法调用事物方法需要二个都起作用需要配置这个东东)
public interface Calculate { /** * 加法 * @param numA * @param numB * @return */ int add(int numA,int numB); /** * 减法 * @param numA * @param numB * @return */ int reduce(int numA,int numB); /** * 除法 * @param numA * @param numB * @return */ int div(int numA,int numB); /** * 乘法 * @param numA * @param numB * @return */ int multi(int numA,int numB); int mod(int numA,int numB); } public class TulingCalculate implements Calculate { public int add(int numA, int numB) { return numA+numB; } public int reduce(int numA, int numB) { return numA-numB; } public int div(int numA, int numB) { return numA/numB; } public int multi(int numA, int numB) { return numA*numB; } public int mod(int numA,int numB){ int retVal = ((Calculate) AopContext.currentProxy()).add(numA,numB); //int retVal = this.add(numA,numB); return retVal%numA; } }
*代理对象调用源代码:*
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation; Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Class<?> targetClass = null; Object target = null; try { Object retVal; //是否暴露代理对象 if (this.advised.exposeProxy) { //把代理对象添加到TheadLocal中 oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } //获取被代理对象 target = targetSource.getTarget(); if (target != null) { //设置被代理对象的class targetClass = target.getClass(); } //把增强器转为方法拦截器链 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); //若方法拦截器链为空 if (chain.isEmpty()) { //通过反射直接调用目标方法 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { //创建方法拦截器调用链条 invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); //执行拦截器链 retVal = invocation.proceed(); } //获取方法的返回值类型 Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { //如果方法返回值为 this,即 return this; 则将代理对象 proxy 赋值给 retVal retVal = proxy; } //如果返回值类型为基础类型,比如 int,long 等,当返回值为 null,抛出异常 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); } } } =====================org.springframework.aop.framework.AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice=========== 把增强器中转为方法拦截器链 public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) { //从缓存中获取缓存key 第一次肯定获取不到 MethodCacheKey cacheKey = new MethodCacheKey(method); //通过cacheKey获取缓存值 List<Object> cached = this.methodCache.get(cacheKey); //从缓存中没有获取到 if (cached == null) { //获取所有的拦截器 cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice( this, method, targetClass); //放入缓存..... this.methodCache.put(cacheKey, cached); } return cached; } =====================org.springframework.aop.framework.AdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice==== public List<Object> getInterceptorsAndDynamicInterceptionAdvice( Advised config, Method method, Class<?> targetClass) { //创建拦截器集合长度是增强器的长度 List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length); Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass()); boolean hasIntroductions = hasMatchingIntroductions(config, actualClass); AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); //遍历所有的增强器集合 for (Advisor advisor : config.getAdvisors()) { //判断增强器是不是PointcutAdvisor if (advisor instanceof PointcutAdvisor) { //把增强器转为PointcutAdvisor PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor; //通过方法匹配器对增强器进行匹配 if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) { MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher(); //能够匹配 if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) { //把增强器转为拦截器 MethodInterceptor[] 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)); } } } } 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 { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } return interceptorList; }
------------------------------------------------------------ 完 --------------------------------------------------------------------
背景知识:
@EnableAspectJAutoProxy(exposeProxy = true) 这个东东是用来干什么的?
没有配置exposeProxy 暴露代理对象的时候我们方法调用
我们在Mod方法中 通过this来调用本类的方法add()方法的时候,发现add()的方法不会被拦截
而我们配置了后exposeProxy的属性,我们发现可以通过
**int retVal = ((Calculate) AopContext.currentProxy()).add(numA,numB);
**
调用的时候,发现了add()方法可以被拦截
原理:把这个exposeProxy设置为true,会把代理对象存放在线程变量中,
AopContext.currentProxy())是从线程变量中获取代理对象(源码中分析)
应用场景(事物方法调用事物方法需要二个都起作用需要配置这个东东)
热门文章
- 「1月7日」最高速度18.6M/S,2025年Clash Nyanpasu每天更新免费节点订阅链接
- 「2月11日」最高速度22.7M/S,2025年Clash Nyanpasu每天更新免费节点订阅链接
- 用指针低三位存放额外信息的优化方法 – 程鑫 _在线工具
- 「1月18日」最高速度22M/S,2025年Clash Nyanpasu每天更新免费节点订阅链接
- VUE前端开发环境版本查看命令方法详解
- 「12月5日」最高速度18.5M/S,2024年Clash Nyanpasu每天更新免费节点订阅链接
- 长期养猫的危害(长期养猫的人对健康有什么影响)
- 「11月20日」最高速度21.8M/S,2024年Clash Nyanpasu每天更新免费节点订阅链接
- 动物疫苗一般在哪里打针的 动物疫苗在哪里购买
- Golang开发gRPC服务详解