Spring AOP 代理类,BeanNameAutoProxyCreator cglib
BeanNameAutoProxyCreator支持拦截接口和类,但不支持已经被jdk代理过的类$Proxy8。使用cglib才能代理,如下
<!-- 通过bean的名字来匹配选择要代理的bean,在使用时仍用原有bean的id从context中获取 -->
<bean id="autoProxy"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<!-- 需要代理的service,以userService结尾注册的bean -->
<property name="beanNames">
<list>
<value>*userService</value>
<value>*routeService</value>
</list>
</property>
<!-- 拦截器的名称 -->
<property name="interceptorNames">
<list>
<value>validateUserAdvisor</value>
<!-- 性能监视增强 -->
<value>performanceMonitorAdvice</value>
</list>
</property>
<!-- 设置强制使用CGLIB生成代理,此时代理的bean如果已经是代理则必须也是由cglib生成的 -->
<property name="optimize" value="true" />
</bean>
optimize是ProxyConfig的属性。意思为 是否对生产代理策略使用优化。
public class ProxyConfig implements Serializable {
private boolean proxyTargetClass = false;
private boolean optimize = false;
boolean opaque = false;
boolean exposeProxy = false;
private boolean frozen = false;
}
一个例子
Spring AOP 提供一个可根据Bean名称来自动生产代理的工具,它就是BeanNameAutoProxyCreator。它的配置是这样:
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="*impl"></property> <!-- 只为后缀为"impl"的bean生产代理 -->
<property name="interceptorNames" value="aServiceAdvisor"></property> <!-- 一个增强 -->
<property name="optimize" value="true"></property> <!-- 是否对代理策略进行优化 -->
</bean>
以上使用BeanNameAutoProxyCreator 只为后缀为"impl"的Bean生产代理。需要注意的是,这个地方我们不能定义代理接口,也就是interfaces属性,因为我们根本就不知道这些Bean到低实现了多少接口。此时不能代理接口,而只能代理类。所以这里提供了一个新的配置项,它就是optimize。如果为true,则可以对代理生成策略进行优化(默认为false)。也就是说,如果该类有接口,就代理接口(使用JDK代理);如果没有接口,就代理类(使用CGLIB代理)。并非像之前的使用的proxyTargetClass 属性那样,强制代理类,而不去考虑代理接口的方式。
那么就有一个问题了,既然有了CGLIB 可以代理任何类了,那为什么还要JDK的动态代理了?
是因为CGLIB 创建有个特点(创建慢,执行块),然而JDK刚好相反(创建快,执行慢)。如果在运行的时候不断的用CGLIB去创建代理,系统的性能会大打折扣,所以建议一般在系统初始化的使用用CGLIB去创建代理,并放入spring的ApplicationContext中以备后用。
流程分析
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
ProxyTargetClass (是否强制使用CGLIB来实现代理)
(true : 强制使用CGLIB来实现代理)
(false : 不强制使用CGLIB来实现代理,首选JDK来实现代理)(默认值)
isOptimize (是否对生成代理策略进行优化)
(true : 进行优化,如果有接口就代理接口(使用JDK动态代理),没有接口代理类(CGLIB代理))
(false : 不进行优化) (默认值)
Spring注入bean失败Failed to convert property value of type
Failed to convert property value of type [$Proxy13
Failed to convert property value of type [$Proxy13] to required type
PropertyAccessException 1: org.springframework.beans.TypeMismatchException: Failed to convert property value of type [$Proxy13] to required type [com.makeprogress.dao.AuthorDaoImp] for property 'authorDaoImp'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy13] to required type [com.makeprogress.dao.AuthorDaoImp] for property 'authorDaoImp': no matching editors or conversion strategy found
Caused by:
org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessException details (1) are:
PropertyAccessException 1:
org.springframework.beans.TypeMismatchException: Failed to convert property value of type [$Proxy13] to required type [com.makeprogress.dao.AuthorDaoImp] for property 'authorDaoImp'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy13] to required type [com.makeprogress.dao.AuthorDaoImp] for property 'authorDaoImp': no matching editors or conversion strategy found
Caused by:
java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy13] to required type [com.makeprogress.dao.AuthorDaoImp] for property 'authorDaoImp': no matching editors or conversion strategy found
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:231)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:138)
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:815)
当系统出现类似上面的异常信息时,很可能你引用了已经实现了自动代理的Bean, Cannot convert value of type [$Proxy13] to required type [com.makeprogress.dao.AuthorDaoImp] for property 'authorDaoImp' 提示的意思:你将authorDaoImp注入到一个spring受管Bean中, 但是spring容器提示你注入的Bean类型不对,它说你注入的是 [$Proxy13] 类型,这就说明你可能在无意中将authorDaoImp实现了代理, 此时你再在spring容器中引用 authorDaoImp时得到的将是代理类型。示例如下(在数据源,事务管理器配置完整的前提下):
http://grey2.iteye.com/blog/994926
A less preferable option is to specify proxy-target-class="true" to your transactional aspect (or whatever makes proxies around your objects)
https://stackoverflow.com/questions/5427077/failed-to-convert-property-value-of-type-proxy1-to-required-type
Spring AOP 代理类,BeanNameAutoProxyCreator cglib的更多相关文章
- jdk动态代理与cglib代理、spring aop代理实现原理
原创声明:本博客来源与本人另一博客[http://blog.csdn.net/liaohaojian/article/details/63683317]原创作品,绝非他处摘取 代理(proxy)的定义 ...
- jdk动态代理与cglib代理、spring aop代理实现原理解析
原创声明:本博客来源为本人原创作品,绝非他处摘取,转摘请联系博主 代理(proxy)的定义:为某对象提供代理服务,拥有操作代理对象的功能,在某些情况下,当客户不想或者不能直接引用另一个对象,而代理对象 ...
- 何为代理?jdk动态代理与cglib代理、spring Aop代理原理浅析
原创声明:本博客来源为本人原创作品,绝非他处摘取,转摘请联系博主 代理(proxy)的定义:为某对象提供代理服务,拥有操作代理对象的功能,在某些情况下,当客户不想或者不能直接引用另一个对象,而代理对象 ...
- jdk动态代理与cglib代理、spring Aop代理原理-代理使用浅析
原创声明:本博客来源为本人原创作品,绝非他处摘取,转摘请联系博主 代理(proxy)的定义:为某对象提供代理服务,拥有操作代理对象的功能,在某些情况下,当客户不想或者不能直接引用另一个对象,而代理对象 ...
- Spring AOP代理时 ClassCastException: $Proxy0 cannot be cast to (类型转换错误)
Spring AOP代理时 ClassCastException: $Proxy0 cannot be cast to (类型转换错误) 问题: 今天在用AfterReturningAdvice时,a ...
- Spring AOP 实现原理与 CGLIB 应用
https://www.ibm.com/developerworks/cn/java/j-lo-springaopcglib/ AOP(Aspect Orient Programming),也就是面向 ...
- Spring AOP 实现原理与 CGLIB 应用--转
AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理.安全检查.缓存.对象池管理等.AOP 实现的关键就在于 ...
- java中代理,静态代理,动态代理以及spring aop代理方式,实现原理统一汇总
若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的. 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. ...
- 【转】Spring AOP 实现原理与 CGLIB 应用
AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理.安全检查.缓存.对象池管理等.AOP 实现的关键就在于 ...
随机推荐
- Scala 系列(五)—— 集合类型综述
一.集合简介 Scala中拥有多种集合类型,主要分为可变的和不可变的集合两大类: 可变集合: 可以被修改.即可以更改,添加,删除集合中的元素: 不可变集合类:不能被修改.对集合执行更改,添加或删除操作 ...
- .Net工具类--表达式目录树解析DataReader和DataTable
一.概述 在项目中经常会使用SQL去操作数据库,在读取数据的时候返回结果一般是DataReader和DataSet,其中DataaSet里面可以包含多个DataTable. 读取到数据之后,一般情况下 ...
- html 快速布局
1.每个单词的首字母大写 一般我们会用JS实现,其实CSS就可以实现.JS代码: var str = 'hello world'; str.replace(/( |^)[a-z]/g,(L)=> ...
- Bootstrap3-导航
Bootstrap 导航 1. 定义导航组件 基本结构: <!-- 基本导航组件 --> <ul class="nav"> <li class=&qu ...
- vue中路由在新的标签页打开
如下 let routeData = this.$router.resolve({ name: 'commercialPreview', query: {cylType: this.$route.qu ...
- vue知识点小结
vue.js中==和===的区别 1.== 用于比较.判断两者相等,比较时可自动换数据类型 2.=== 用于(严格)比较.判断两者(严格)相等,不会进行自动转换,要求进行比较的操作数必须类型一致,不一 ...
- English--倒装句
English|倒装句 这一块主要进行英语中倒装句与强调句的透析,希望大家可以掌握倒装句.因为倒装句,实在是太常见了,加油哦~~ 前言 目前所有的文章思想格式都是:知识+情感. 知识:对于所有的知识点 ...
- flask中的static_path和static_path_url和static_folder
static_folder表示静态文件所在路径,默认为root_dir下的static文件夹 static_url_path的行为比较复杂 如果static_folder未被指定(也就是默认值stat ...
- String类常用功能
String类常用功能 判断: boolean equals(Object obj) boolean equalsIgnoreCase(String str) //忽略大小写 boolean star ...
- ES6 Class(类)(九)
一.Class类1.构造函数 constructor(){} 说明:a.如果没有重新定义带参数的构造函数,类会默认为我们提供一个不带参数的隐式构造函数b.在创建类的实例时会自动调用类中的构造函数 2. ...