当前位置: 首页 > news >正文

一个人做导购网站/网络营销薪酬公司

一个人做导购网站,网络营销薪酬公司,广州做网站的公司,销售网站开发与设计现状背景最近工作中需要对组内各个系统依赖的第三方接口进行监控报警,对于下游出现问题的接口能够及时感知.首先我们写了一个Spring AOP注解,用于收集调用第三方时返回的信息.而我们调用第三方的类抽象出一个父类.并在父类的方法中加入我们的自定义注解用于监控日志并打印日志.很多…

背景

最近工作中需要对组内各个系统依赖的第三方接口进行监控报警,对于下游出现问题的接口能够及时感知.首先我们写了一个Spring AOP注解,用于收集调用第三方时返回的信息.而我们调用第三方的类抽象出一个父类.并在父类的方法中加入我们的自定义注解用于监控日志并打印日志.

2219e2abdca3c1f135970a1576d09110.png

很多子类继承了这个父类并使用父类中的方法.如:

cd5cc5dd6e2fb59db136639291f6ac48.png

当调用子类的doSomething方法时问题出现了,发现Spring AOP没有拦截doPost()方法.而将注解加在子类方法上时,Spring AOP可以拦截子类的方法,但这不是我们想要的结果.而当我们将父类通过@Autowired方式注入到子类中代替使用继承的方式调用父类中方法时Spring AOP可以拦截父类中的方法.至此发现问题出现在继承上面.

原因分析

Spring AOP拦截器的实现原理就是利用动态代理技术实现面向切面编程,Spring 的代理实现有两种:一是基于 JDK Dynamic Proxy 技术而实现的;二是基于 CGLIB 技术而实现的。如果目标对象实现了接口,在默认情况下Spring会采用JDK的动态代理实现AOP,在本例目标对象没有实现接口,因此使用的CGLIB实现动态代理对SuperClass对象进行代理,然后增强doPost()方法.下面的代码展示了为什么Spring AOP没有增强doPost()方法.

d54037b2e63e514de70aaa2db5edb96d.png

图2等价于图3,即使用super关键字调用doPost()方法,这就表明我们使用的SuperClass的实例调用的doPost()方法,在我们在使用Spring AOP的时候,我们从IOC容器中获取的Bean对象其实都是代理对象,而不是那些Bean对象本身.因此AOP不能使用代理对象调用这些父类的方法.

解决方案

知道了问题原因,解决问题就比较容易了,由于我们使用的super关键字调用父类的方法行不通,那么我们就强制使用代理对象调用父类方法.

05fd02d4424ace0dc1b40cc9e9f233fc.png

好了,我们运行程序,发现不但没有拦截方法而且还报错了.

java.lang.IllegalStateException: Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.

1

异常信息非常明确,找不到当前的代理,需要在暴露出代理,我们看下AopContext这个类的源码,看看到底哪里出错了,看到了我们输出错误信息的地方.

package org.springframework.aop.framework;

import org.springframework.core.NamedThreadLocal;

import org.springframework.lang.Nullable;

public final class AopContext {

private static final ThreadLocalcurrentProxy = new NamedThreadLocal("Current AOP proxy");

private AopContext() {

}

public static Object currentProxy() throws IllegalStateException {

Object proxy = currentProxy.get();

if (proxy == null) {

throw new IllegalStateException("Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.");

} else {

return proxy;

}

}

@Nullable

static Object setCurrentProxy(@Nullable Object proxy) {

Object old = currentProxy.get();

if (proxy != null) {

currentProxy.set(proxy);

} else {

currentProxy.remove();

}

return old;

}

}

说名setCurrentProxy方法没有被调用,通过查找发现有两个类调用了该方法,分别为CglibAopProxy和JdkDynamicAopProxy,是不是很熟悉,这两个就是Spring aop的代理方式,由于我们讨论的目标对象不是基于接口的,因此本文使用的代理都是基于CglibAopProxy,我们找到该类中调用setCurrentProxy方法的地方,程序中判断this.advised.exposeProxy是否为true,如果为true,设置当前代理,而通过调试这个字段为false

if (this.advised.exposeProxy) {

oldProxy = AopContext.setCurrentProxy(proxy);

setProxyContext = true;

}

1

2

3

4

那么我们就在需要通知的地方,即你需要拦截方法的类上加上如下注解.

@EnableAspectJAutoProxy(exposeProxy = true)

1

这次在调用,发现已经可以拦截注解标注的方法了.

后记

解决这个问题的方式有很多,可以子类不继承父类,而是改为@Autowired方式,然后每一个调用的地方需要加上父类的对象.

最终我们在程序中的方案是加了一个父类的代理类,用于强制使用代理对象调用父类的方法.而原来父类的子类继承代理类即可.

import org.springframework.aop.framework.AopContext;

import org.springframework.stereotype.Component;

import java.util.Map;

@Component

public class ProxyAgent extends BaseAgent{

private BaseAgent getProxyObject() {

return ((BaseAgent)AopContext.currentProxy());

}

protected String doGet(String url, Mapheaders, Mapparams, Object... uriVariables) {

return getProxyObject().doGetBase(url, headers, params, uriVariables);

}

protected String doPost(String url, Mapheaders, Object body) {

return getProxyObject().doPostBase(url, headers, body);

}

protected String doPostForm(String url, Mapparams) {

return doPostForm(url, null, params);

}

protected String doPostForm(String url, Mapheaders, Mapparams) {

return getProxyObject().doPostFormBase(url, headers, params);

}

protected String doPostFormWithContentHeader(String url, Mapheaders,

Mapparams, byte[] boundary) {

return getProxyObject().doPostFormWithContentHeaderBase(url, headers, params, boundary);

}

protected String doPostFormUpload(String url, Mapheaders, Mapparams) {

return getProxyObject().doPostFormUploadBase(url, headers, params);

}

}

同理,调用内部方法使用this关键字时同样会出现这个问题,同样采用强制使用代理对象即可.

http://www.lbrq.cn/news/778681.html

相关文章:

  • 集团响应式网站建设/中国十大it培训机构排名
  • 完成一个个人主页网站的制作/网址导航该如何推广
  • 网站空间一般有多大/网站百度seo关键词优化
  • dede怎么做动态网站/小程序制作
  • 怎样才能做公司的网站/比较正规的代运营
  • 编程教学网站推荐/seo外链怎么做
  • 做淘宝网站要安全保障么/企业seo优化服务
  • 微网站免费模板/深圳seo优化公司
  • 网站后台灰色/seo排名优化方式
  • 山东住房和城乡建设厅网站一体化平台/营销方案案例
  • 襄阳做网站公司有哪些/大型营销型网站制作
  • 张店网站开发招聘/网络营销中心
  • 亳州网站建设公司/百度广告客服电话
  • 制作商业网站/百度云搜索引擎官网入口
  • 金泉网做网站推广/福州百度网站排名优化
  • 上海网站建设-网建知识/青岛谷歌优化
  • 百度云服务器做asp网站/前端性能优化
  • 建一个网站一般要多少钱/网络营销的未来发展趋势论文
  • 做不锈钢管网站/厦门人才网个人版
  • 怎样优化网站自然排名/企业网站seo诊断工具
  • 免费做app网站建设/海阳seo排名
  • 郴州网站建设有限公司/关键词查询工具
  • 服务之家做网站简单吗/网站关键词优化有用吗
  • 网站开发和移动开发/百度网址名称是什么
  • 直播视频网站/seo职位
  • 多人在线网站开发/网站建设公司好
  • 网站建设好后怎么制作网页/外呼系统电销
  • 做电影解析网站/搜索引擎排名中国
  • 织梦cms零基础做网站/竞价托管代运营
  • 做的漂亮的商务网站/市场推广方案怎么写
  • Linux下安装jdk
  • 【MySQL基础篇】:MySQL索引——提升数据库查询性能的关键
  • MySQL 处理重复数据详细说明
  • 第4章 程序段的反复执行for语句P115练习题(题及答案)
  • Jmeter性能测试之安装及启动Jmeter
  • Docker大全