- 浏览: 1584205 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
jsrgzhangzhiyong:
关于null值的转换还是感觉不太友好,就像 mapstruct ...
我也造了个轮子:BeanMapping(属性拷贝) -
he037:
a417930422 写道引用使用EPHEMERAL会引出一个 ...
基于zookeeper的分布式lock实现 -
seancheer:
qianshangding 写道首先节点启动后,尝试读取本地的 ...
zookeeper学习记录三(session,watcher,persit机制) -
雪夜归人:
您好,我想咨询一下,开源的canal都能支持mysql的哪些版 ...
Canal BinlogChange(mysql5.6) -
zhoudengyun:
copy 一份做记录,后续学习,请知悉
阿里巴巴开源项目: 基于mysql数据库binlog的增量订阅&消费
背景
最近在实施并行加载,遇到一个问题: 重复代理,或者说是两次cglib代理。
主要是并行加载技术本身是采用了cglib+拦截的技术进行控制,所以势必会要求进行一次代理配置那
1. 如果需要代理的原始对象已经是一个cglib代理后的对象,比如性能监控,日志记录等等。
2. 其他同事在做的自动路由,按需加载都会要求进行一次cglib代理
如何平衡多次代理的问题,就冒出来了。
思路
接近于spring的autoProxyCretor的一套机制,利用了BeanPostProcessor,就是在bean的生命周期上做点文章。
spring默认提供的几种auto-proxy:
- BeanNameAutoProxyCreator : 可以配置需要被进行auto-proxy的bean names列表,它控制的是需要代理的bean列表
- InfrastructureAdvisorAutoProxyCreator
- DefaultAdvisorAutoProxyCreator : 将对应匹配的advisor,自动添加到spring的bean。它控制的是advisor的匹配,所有的bean都会被自动代理
切入代码:
public Object postProcessBeforeInitialization(Object bean, String beanName) { // 不做处理 return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); return wrapIfNecessary(bean, beanName, cacheKey); } return bean; }
if (ProxyFactoryBean.class.isAssignableFrom(bean.getClass())) { ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean) bean; String[] orignInterceptorNames = getInterceptorFromProxyFactoryBean(proxyFactoryBean); String[] newInterceptorNames = new String[orignInterceptorNames.length + interceptorNames.length]; if (applyCommonInterceptorsFirst) {// 如果是true,则将Auto-proxy的拦截器定义到最前面 // 构造新的的拦截器列表 System.arraycopy(interceptorNames, 0, newInterceptorNames, 0, interceptorNames.length); System.arraycopy(orignInterceptorNames, 0, newInterceptorNames, interceptorNames.length, orignInterceptorNames.length); } else { System.arraycopy(orignInterceptorNames, 0, newInterceptorNames, 0, orignInterceptorNames.length); System.arraycopy(interceptorNames, 0, newInterceptorNames, orignInterceptorNames.length, interceptorNames.length); } // 重新设置新的inteceptorNames proxyFactoryBean.setInterceptorNames(newInterceptorNames); return proxyFactoryBean; } else { // 如果是单例,对应的代理bean对象为同一个 ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean(); proxyFactoryBean.setBeanFactory(beanFactory); proxyFactoryBean.setBeanClassLoader(proxyClassLoader); proxyFactoryBean.setInterceptorNames(interceptorNames); proxyFactoryBean.copyFrom(this); // 拷贝对应的一些Proxy config proxyFactoryBean.setTarget(bean); return proxyFactoryBean.getObject(); }
<!-- 多例测试 --> <bean id="asyncLoadTestServiceForCompsitePrototype" class="com.agapple.asyncload.domain.AsyncLoadTestServiceImpl" scope="prototype" /> <!-- 单例测试 --> <bean id="asyncLoadTestServiceForCompsiteSingleton" class="com.agapple.asyncload.domain.AsyncLoadTestServiceImpl" scope="singleton" /> <!-- 原本是ProxyFactoryBean --> <bean id="logInteceptor" class="com.agapple.asyncload.spring.LogInteceptor" /> <bean id="asyncLoadTestServiceForCompsiteFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean" scope="prototype"> <property name="interceptorNames"> <list> <value>logInteceptor</value> </list> </property> <property name="targetName" value="asyncLoadTestService" /> <property name="proxyTargetClass" value="true" /> <!-- 强制申明为cglib代理 --> </bean> <!-- 第一次融合代理 --> <bean class="com.agapple.asyncload.impl.spring.CompositeAutoProxyCreator"> <property name="beanNames"> <list> <value>asyncLoadTestServiceForCompsitePrototype</value> <value>asyncLoadTestServiceForCompsiteSingleton</value> <value>asyncLoadTestServiceForCompsiteFactoryBean</value> <!-- 代理的对象原本已经是一个proxyFactoryBean的final cglib--> </list> </property> <property name="interceptorNames"> <list> <value>asyncLoadInterceptor</value> </list> </property> </bean> <!-- 多次的代理会只作用于一个代理对象 --> <bean class="com.agapple.asyncload.impl.spring.CompositeAutoProxyCreator"> <property name="applyCommonInterceptorsFirst" value="true"/> <property name="beanNames"> <list> <value>asyncLoadTestServiceForCompsitePrototype</value> <value>asyncLoadTestServiceForCompsiteSingleton</value> <value>asyncLoadTestServiceForCompsiteFactoryBean</value> <!-- 代理的对象原本已经是一个proxyFactoryBean的final cglib--> </list> </property> <property name="interceptorNames"> <list> <value>logInteceptor</value> </list> </property> </bean>
代码
配置文件:https://code.google.com/p/asyncload/source/browse/trunk/src/test/resources/asyncload/applicationContext.xml,查找对应的Compsite
最后
在查找具体的解决方案是一个比较曲折的过程,基本上把ProxyFactoryBean机制,auto-proxy机制代码实现都看了一遍。
过程1 : 原先是寄希望于spring可以提供类似的一个global advisor的概念,每个ProxyFatoryBean除了自己配置的inteceptorNames的拦截器之外,还回从一些global的定义中获取一些大家公用的advisor。找了一圈发现没有,曾经的GlobalAdvisorAdapterRegistry给了我一些希望,最后发现是一个绝望的内容。
过程2:在看AutoProxyCreator那套机制时,其实它预留了一些扩展点,主要是根据bean name获取对应的auto-proxy信息。bean name到具体的bean的处理,因为是在BeanPostProcessor,处于getBean()生命周期的最后一步,如果此时进行this.beanFactory.getBean()就是一个死循环,此路不通,所以原先的auto-proxy相关的扩展点基本走不同。
过程3: 在2走不通后,一直在琢磨是否可以通过直接处理生成后的object,获取原始object对应的ProxyFactoryBean.getAdvsisor()方法。后来看了半天代码,发现也是条思路,因为proxyFactoryBean生成的proxy对象完全和ProxyFactoryBean无关,也就不会有getAdvisor()方法,因为生成的cglib代理或者jdk代理,cglib代理到还有对advised的引用持有,有办法通过反射获取。而jdk那个压根没则,所以有是一条思路。
过程4: 2,3都走不通了,今天在debug另一个问题时,发现BeanPostProcessor的相应callback方法中传递的bean object居然是原生的ProxyFactoryBean,也就是说未进行getObject()调用之前的原始对象。大喜,总于找到突破口,最后就是自己实现了一套auto-proxy机制,因为原先的扩展点不支持传递bean object对象。
最后只能说自己对spring的一些机制还不够了解,需要持续加强。发现去扩展spring的一些点,是学习spring最快的一种方式,找扩展点的过程是对spring的一个总体把握的过程
悟了3天的问题,总于有了解决方案,仅以此文几年一下我那3天死去的脑细胞!!
发表评论
-
yugong QuickStart
2016-03-05 01:52 0几点说明 a. 数据迁移的方案可参见设计文档,oracl ... -
阿里巴巴开源项目: 阿里巴巴去Oracle数据迁移同步工具
2016-03-05 18:29 6350背景 08年左右,阿里巴巴开始尝试MySQL的相关 ... -
愚公performance
2016-03-02 17:29 0性能测试 全量测试 场景1 (单主键, ... -
yugong AdminGuide
2016-03-02 16:40 0环境要求 操作系统 数据库 迁移方案 部署 ... -
Tddl_hint
2014-01-27 13:52 0背景 工作原理 Hint格式 direct模 ... -
tddl5分库规则
2014-01-26 14:41 0背景 工作原理 构建语法树 元数据 基于 ... -
tddl5优化器
2014-01-22 15:12 0背景 工作原理 构建语法树 元数据 抽象语 ... -
Canal BinlogChange(mariadb5/10)
2014-01-20 17:25 4455背景 先前开源了一个 ... -
asynload quickstart
2013-10-08 22:49 0几点说明: 1. asyncload是做为一个j ... -
网友文档贡献
2013-09-18 15:50 01. Otter源代码解析系列 链接:http://e ... -
Manager配置介绍
2013-09-16 13:00 0通道配置说明 多种同步方式配置 a. 单向同步 ... -
canal&otter FAQ
2013-09-05 17:30 0常见问题 1. canal和 ... -
阿里巴巴开源项目:分布式数据库同步系统otter(解决中美异地机房)
2013-08-22 16:48 40216项目背景 阿里巴巴B2B公司,因为业务的特性 ... -
Otter AdminGuide
2013-08-19 11:06 0几点说明 otter系统自带了manager,所以简化了一 ... -
Otter高可用性
2013-08-17 23:41 0基本需求 网络不可靠,异地机房尤为明显. man ... -
Otter数据一致性
2013-08-17 23:39 0技术选型分析 需要处理一致性的业务场景: 多地修改 ( ... -
Otter扩展性
2013-08-17 22:20 0扩展性定义 按照实现不同,可分为两类: 数据处理自定 ... -
Otter双向回环控制
2013-08-17 21:37 0基本需求 支持mysql/oracle的异构数据库的双 ... -
Otter调度模型
2013-08-17 20:13 0背景 在介绍调度模型之前,首先了解一下otter系统要解 ... -
Otter Manager介绍
2013-08-16 11:16 0背景 otter4.0发布至 ...
相关推荐
使用mysql5.7+sharding-proxy实现分表,策略为每半年时间分一次表
docker-letsencrypt-nginx-proxy-companion-examples, 结合 Docker gen和 letsencrypt Nginx 代理伙伴的示例 docker-letsencrypt-nginx-proxy-companion-examples这个库是使用 nginx代理插件, docker gen和 docker-...
aws-kube-proxy1.16.8版本示例文件
node-https-proxy-agent, HTTPS端点的HTTP代理 `http.Agent` 实现 https-proxy-agent HTTPS的HTTP代理 http.Agent 实现 这个模块为连接到指定的HTTP或者HTTPS代理服务器提供了 http.Agent 实现,并且可以与内置的...
让Node.js代理变得很简单,可轻松配置代理中间件,用于连接,快速,浏览器同步等等。
browsermob-proxy-2.1.4,与selenium一起进行爬虫,获取network中的链接资源
influx-proxy-2.5.7-linux-amd64.tar.gz
赠送jar包:netty-handler-proxy-4.1.68.Final.jar; 赠送原API文档:netty-handler-proxy-4.1.68.Final-javadoc.jar; 赠送源代码:netty-handler-proxy-4.1.68.Final-sources.jar; 赠送Maven依赖信息文件:netty-...
gcr.io/kubebuilder/kube-rbac-proxy:v0.13.0 镜像
charles 解压就能用 charles-proxy-4.5.6-win64
赠送jar包:netty-handler-proxy-4.1.73.Final.jar; 赠送原API文档:netty-handler-proxy-4.1.73.Final-javadoc.jar; 赠送源代码:netty-handler-proxy-4.1.73.Final-sources.jar; 赠送Maven依赖信息文件:netty-...
赠送jar包:netty-handler-proxy-4.1.73.Final.jar; 赠送原API文档:netty-handler-proxy-4.1.73.Final-javadoc.jar; 赠送源代码:netty-handler-proxy-4.1.73.Final-sources.jar; 赠送Maven依赖信息文件:netty-...
k8s.gcr.io/kube-proxy:v1.15.3镜像tar包,使用 docker load --input kube-proxy_v1.15.3.tar进行导入
flex-messaging-proxy.jarflex-messaging-proxy.jarflex-messaging-proxy.jarflex-messaging-proxy.jar
WinHTTP Web Proxy Auto-Discovery Service 服务处于 停止 状态还有,我的服务器没有使用WEB代理和防火墙客户端。
mysql-proxy(mysql代理).txt 主要是配置 linux 环境下mysql的代理设置功能
代理服务器 BrowserMob Proxy,BrowserMob Proxy 简称 BMP,可以这么说,BMP 绝对是为 Selenium 为生的,Selenium + BMP 的完美搭配,可以实现很多你绝对想象不出来的功能
利用ShardingSphere(sharding-proxy)实现分库分表,通过整合ZooKeeper,进行简单配置文件修改轻松实现跨库跨表相关操作,轻量级零侵入整合项目开发。
kubernetes的k8s.gcr.io/kube-proxy:v1.17.3镜像包,版本为v1.17.3。文件是kube-proxy_v_1_17.3.tar