spring的auto-proxy自动代理(融合机制实现)
背景
最近在实施并行加载,遇到一个问题: 重复代理,或者说是两次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都会被自动代理?
2. ?如果原始对象是proxyFactoryBean,配置的并行加载拦截器是基于同一个proxyFactoryBean3. ?多次的融合机制,是可以进行合并处理。 因为不同的框架会自定义配置一份代理拦截,需要将两份拦截器进行合并处理。
代码实现代码:https://code.google.com/p/asyncload/source/browse/trunk/src/main/java/com/agapple/asyncload/impl/spring/CompositeAutoProxyCreator.java?测试代码:https://code.google.com/p/asyncload/source/browse/trunk/src/test/java/com/agapple/asyncload/spring/AsyncLoadSpringCompsiteTest.java配置文件: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天死去的脑细胞!!