- 浏览: 1583409 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
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的增量订阅&消费
背景
公司在做监控迁移过程中,使用了aop:config进行配置。 配置例子:
<aop:config> <aop:advisor advice-ref="rpc-interceptor" pointcut-ref="rpc-pointcut"/> </aop:config>
定义了一些advisor列表,但在实际过程中却遇到一些莫名奇妙的问题,就是原本不应该被生成代理的对象出现了jdk,cglib代理。
分析
aop:config具体的解析类为//AopNamespaceHandler.java ,通过跟踪分析,最终会创建一个autoProxyCreator。
//========================== public void init() { // In 2.0 XSD as well as in 2.1 XSD. registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser()); registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser()); registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator()); // Only in 2.0 XSD: moved to context namespace as of 2.1 registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); } //========================== ConfigBeanDefinitionParser.java public BeanDefinition parse(Element element, ParserContext parserContext) { CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element)); parserContext.pushContainingComponent(compositeDef); configureAutoProxyCreator(parserContext, element);//构造auto proxy NodeList childNodes = element.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node node = childNodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { String localName = node.getLocalName(); if (POINTCUT.equals(localName)) { parsePointcut((Element) node, parserContext); } else if (ADVISOR.equals(localName)) { parseAdvisor((Element) node, parserContext); } else if (ASPECT.equals(localName)) { parseAspect((Element) node, parserContext); } } } parserContext.popAndRegisterContainingComponent(); return null; } private void configureAutoProxyCreator(ParserContext parserContext, Element element) { AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element); //调用AopNamespaceUtils创建 } //========================== AopNamespaceUtils.java public static void registerAspectJAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement)); useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); registerComponentIfNecessary(beanDefinition, parserContext); } //========================== AopConfigUtils.java public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) { return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source); //创建了AspectJAwareAdvisorAutoProxyCreator }
最后创建的AutoProxyCreator为: AspectJAwareAdvisorAutoProxyCreator
用过DefaultAdvisorAutoProxyCreator的应该知道:
1. 它会自动扫描当前spring容器中的Advisor,自动将当前容器中的bean进行代理
2. 至于Advisor是否会对bean生效,主要是取决于对应的pointcut的定义
3. 我们定义的MethodInterceptor,BeforeAdvice等一些Advice事件,本身不是一个完整的Advisor,所以不会被AutoProxyCreator使用。(都是在运行时被wrap成一个Advisor。具体的可以看一下ProxyFactoryBean的代码)
//=========================== //ProxyFactoryBean.java private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance(); //定义了wrap器 //=========================== //DefaultAdvisorAdapterRegistry.java public DefaultAdvisorAdapterRegistry() { registerAdvisorAdapter(new MethodBeforeAdviceAdapter()); registerAdvisorAdapter(new AfterReturningAdviceAdapter()); registerAdvisorAdapter(new ThrowsAdviceAdapter()); } public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException { if (adviceObject instanceof Advisor) { return (Advisor) adviceObject; } if (!(adviceObject instanceof Advice)) { throw new UnknownAdviceTypeException(adviceObject); } Advice advice = (Advice) adviceObject; if (advice instanceof MethodInterceptor) { // So well-known it doesn't even need an adapter. return new DefaultPointcutAdvisor(advice); } for (int i = 0; i < this.adapters.size(); i++) { // Check that it is supported. AdvisorAdapter adapter = (AdvisorAdapter) this.adapters.get(i); if (adapter.supportsAdvice(advice)) { return new DefaultPointcutAdvisor(advice); } } throw new UnknownAdviceTypeException(advice); }
AutoProxyCreator机制
在autoProxyCreator javadoc中有明确的定义:
因为默认在AbstractAdvisorAutoProxyCreator定义了findCandidateAdvisors的行为: (扫描spring容器中所有的Advisor)
//===========================
//AbstractAdvisorAutoProxyCreator.java
protected List findCandidateAdvisors() {
return this.advisorRetrievalHelper.findAdvisorBeans();
}
//===========================
//BeanFactoryAdvisorRetrievalHelper.java
public List findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = null;
synchronized (this) {
advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false); //从容器中获取Advisor的定义
this.cachedAdvisorBeanNames = advisorNames;
}
}
.......
}
return advisors;
}
而在DefaultAdvisorAutoProxyCreator和AspectJAwareAdvisorAutoProxyCreator,AnnotationAwareAspectJAutoProxyCreator等,都是有扫描所有Advisor的动作。
结论
结论其实很明显了
- 因为使用了aop:config,创建了一个AspectJAwareAdvisorAutoProxyCreator
- AspectJAwareAdvisorAutoProxyCreator会扫描所有的Advisor,检查下pointCut是否匹配
- 我们定义的Advisor中的pointcut,spring的规范是要求:[classname] + [method]. 而我们因为先前都使用了ProxyFactoryBean,都是绑定在一个class使用,所以classname使用了通配符,所以最后的配置为: [.*] + method
- 正因为使用了 [.*] + method的配置,导致该Advisor定义应用到了所有bean,这也就出现了问题。
解决
其实需求很简单,就是想针对指定的匹配的beanName,应用指定的Advisor。
所以最后可以选择BeanNameAutoProxyCreator,如果觉得需要支持pattern的匹配,可以选择自己扩展。
最后
几点思考:
1. AutoProxyCreator 和 手工使用ProxyFactoryBean配置Advisor,尽量别混合使用
2. 深刻了解下spring中Advisor的设计,pointcut和advice。 pointcut是基于 [classname] + [method] 匹配
3. 避免多次的AutoProxyCreator处理,重复的cglib的代理会出现啥情况,相信大家都知道。针对这样的需求,自己实现了一个融合多个AutoProxyCreator的cglib代理的实现,可以参考: spring的auto-proxy自动代理(融合机制实现)
最后,整个问题的排查过程,主要是我的一个同事给力的比较多,因为对aop:config不熟悉,我只是提供一些spring aop使用的经验
评论
恩,其实想表达的观点是:
类似DefaultAdvisorAutoProxyCreator(自动代理)和自定义的ProxyFactoryBean配置Advisor(手工配置)别混用,除非你对其有比较深刻的理解。
水还是比较深的,平时多看看源码,了解下spring的一些设计理念
发表评论
-
yugong QuickStart
2016-03-05 01:52 0几点说明 a. 数据迁移的方案可参见设计文档,oracl ... -
阿里巴巴开源项目: 阿里巴巴去Oracle数据迁移同步工具
2016-03-05 18:29 6340背景 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 4447背景 先前开源了一个 ... -
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 40209项目背景 阿里巴巴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发布至 ...
相关推荐
配置可以通过xml文件来进行,大概有四种方式: 1. 配置ProxyFactoryBean,显式地设置advisors, advice, target等(基于代理的AOP ) ...4. 通过<aop: aspectj-autoproxy>来配置,使用AspectJ的注解来标识通知及切入点
Spring2.5开发 如果我们用到了AOP的话 一定需要aspectjrt.jar + aspectjweaver.jar 两个jar文件 这里面提供了 导入这两个就可以进行AOP开发了
xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd ...
package com.gc.autoproxy下为:aop方式自动代理 package com.gc.cglib下为:aop方式cglib代理 package com.gc.dynproxy下为:aop方式动态代理 package com.gc.javaproxy下为:java代理机制实现 package ...
spring对AOP的支持 1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP 3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK...
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy> xml中要有这句,可以解决子类类报错的问题。 或者去掉这句话,同时去掉public class AccountServiceImpl implements AccountService {...
aop分析笔记 个人总结所得 org.springframework.aop.framework.autoproxy
Nepxion矩阵 Nepxion Matrix是一种集成的Spring AutoProxy,Spring Registrar和Spring Import Selector三种机制的AOP框架,具有很高的通用性,健壮性,可选和易用性请联系我微信,钉钉,公众号和文档简介Spring自动...
autoproxy-gfwlist 的镜 ( )。 如果您无法加载 ,请使用以下命令: 或trunk分支中的一个: 不喜欢这个自述文件? 切换到,这与官方的svn repo完全相同。
AutoProxy现代化,更快,更易于使用。 从。 Mozilla的附加评论对我来说太慢了。 第一次全面审核仍在排队中。 因此,我提供了这种替代安装方式。 在Mozilla的附加站点上。
注意:使用注解的方式,最终通知和后置通知顺序换了,建议使用环绕通知 注解 配置 声明式事务管理 PlatFormTransactionManager:平台事务管理器:定义了commit/rollback Mybatis/jdbc:...
spring实现的自动代理配置!用到的关键类org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator
6.4.2. Spring AOP中使用@AspectJ还是XML? 6.5. 混合切面类型 6.6. 代理机制 6.7. 编程方式创建@AspectJ代理 6.8. 在Spring应用中使用AspectJ 6.8.1. 在Spring中使用AspectJ来为domain object进行依赖注入 6.8.1.1....
6.4.2. Spring AOP中使用@AspectJ还是XML? 6.5. 混合切面类型 6.6. 代理机制 6.7. 编程方式创建@AspectJ代理 6.8. 在Spring应用中使用AspectJ 6.8.1. 在Spring中使用AspectJ来为domain object进行依赖注入 ...
6.4.2. Spring AOP中使用@AspectJ还是XML? 6.5. 混合切面类型 6.6. 代理机制 6.6.1. 理解AOP代理 6.7. 以编程方式创建@AspectJ代理 6.8. 在Spring应用中使用AspectJ 6.8.1. 在Spring中使用AspectJ进行domain ...
6.4.2. Spring AOP中使用@AspectJ还是XML? 6.5. 混合切面类型 6.6. 代理机制 6.6.1. 理解AOP代理 6.7. 以编程方式创建@AspectJ代理 6.8. 在Spring应用中使用AspectJ 6.8.1. 在Spring中使用AspectJ进行domain ...
6. 使用Spring进行面向切面编程(AOP) 6.1. 简介 6.1.1. AOP概念 6.1.2. Spring AOP的功能和目标 6.1.3. Spring的AOP代理 6.2. @AspectJ支持 6.2.1. 启用@AspectJ支持 6.2.2. 声明一个切面 6.2.3. 声明一个...
03. xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" 04. xmlns:p=...
AutoProxy 能自动识别实际网络位置,并切换到相应的文件更改代理服务器设置,默认打印机和默认主页。 特性: - 自动识别实际网络 - 自动启动网络配置(代理/打印机/初始页) - 维护网络资料 - 这每个...
AutoProxy修改版,解决火狐自带的AutoProxy不能添加规则的问题