工作读框架的代码时常遇到cglib的东东,初看会有点摸不着头脑,打断点debug才发觉得cglib很强大。
回到家把源码下下来,呵呵,还带有sample code,下载地址见cglib sourceforge
。
下面是sample code:
1. Bean.java
package samples;
import java.beans.*;
/**
*
* @author baliuka
*/
public abstract class Bean implements java.io.Serializable{
String sampleProperty;
abstract public void addPropertyChangeListener(PropertyChangeListener listener);
abstract public void removePropertyChangeListener(PropertyChangeListener listener);
public String getSampleProperty(){
return sampleProperty;
}
public void setSampleProperty(String value){
this.sampleProperty = value;
}
public String toString(){
return "sampleProperty is " + sampleProperty;
}
}
2. Beans.java
package samples;
import java.beans.*;
import java.lang.reflect.*;
import net.sf.cglib.proxy.*;
/**
*
* @author baliuka
*/
public class Beans implements MethodInterceptor {
private PropertyChangeSupport propertySupport;
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertySupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
propertySupport.removePropertyChangeListener(listener);
}
public static Object newInstance( Class clazz ){
try{
Beans interceptor = new Beans();
Enhancer e = new Enhancer();
e.setSuperclass(clazz);
e.setCallback(interceptor);
Object bean = e.create();
interceptor.propertySupport = new PropertyChangeSupport( bean );
return bean;
}catch( Throwable e ){
e.printStackTrace();
throw new Error(e.getMessage());
}
}
static final Class C[] = new Class[0];
static final Object emptyArgs [] = new Object[0];
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object retValFromSuper = null;
try {
if (!Modifier.isAbstract(method.getModifiers())) {
retValFromSuper = proxy.invokeSuper(obj, args);
}
} finally {
String name = method.getName();
if( name.equals("addPropertyChangeListener")) {
addPropertyChangeListener((PropertyChangeListener)args[0]);
}else if ( name.equals( "removePropertyChangeListener" ) ){
removePropertyChangeListener((PropertyChangeListener)args[0]);
}
if( name.startsWith("set") &&
args.length == 1 &&
method.getReturnType() == Void.TYPE ){
char propName[] = name.substring("set".length()).toCharArray();
propName[0] = Character.toLowerCase( propName[0] );
propertySupport.firePropertyChange( new String( propName ) , null , args[0]);
}
}
return retValFromSuper;
}
public static void main( String args[] ){
Bean bean = (Bean)newInstance( Bean.class );
bean.addPropertyChangeListener(
new PropertyChangeListener(){
public void propertyChange(PropertyChangeEvent evt){
System.out.println(evt);
}
}
);
bean.setSampleProperty("TEST");
}
}
javac然后java下,执行结果如下:
java.beans.PropertyChangeEvent[source=sampleProperty is TEST]
没想到能够正确跑起来呀,可是samples.Bean明明不是abstract么?呵呵。。。挺有意思,看来cglib会自己帮你实现一些方法。
使用cglib很大一点不就是希望能够对方法进行截拦么,可是目前samples.Bean是使用默认的构造器,那么就不能避免其他的同学直接new samples.Bean(),这样的话,还是达不到截拦的效果。ok,于是乎我把samples.Bean的构建器显示的声明为private,仅仅对samples.Bean.java做如下调整:
public abstract class Bean implements java.io.Serializable{
private Bean() { }
/**
* ... ...
*/
}
经过这么一调整,再次javac,发现没啥问题,接着进行javac samples.Beans,哦哦发现报错罗:
java.lang.IllegalArgumentException: No visible constructors in class samples.Bean
at net.sf.cglib.proxy.Enhancer.filterConstructors(Enhancer.java:531)
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:448)
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
at samples.Beans.newInstance(Beans.java:33)
at samples.Beans.main(Beans.java:76)
Exception in thread "main" java.lang.Error: No visible constructors in class samples.Bean
at samples.Beans.newInstance(Beans.java:38)
at samples.Beans.main(Beans.java:76)
嘻嘻。。。看到了么,No visible constructors in class samples.Bean...
看来构建器不能声明为private呀,samples.Bean的构建器应该至少让samples.Beans可见吧。
好的,难道一定需要参数为空的默认构建器么,再修改下看看:
public abstract class Bean implements java.io.Serializable{
public Bean(Object arg) { }
/**
* ...
*/
}
这把再执行下,又出现Error罗,呵呵...
java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
at net.sf.cglib.proxy.Enhancer.emitConstructors(Enhancer.java:721)
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:499)
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
at samples.Beans.newInstance(Beans.java:33)
at samples.Beans.main(Beans.java:76)
Exception in thread "main" java.lang.Error: Superclass has no null constructors but no arguments were given
at samples.Beans.newInstance(Beans.java:38)
at samples.Beans.main(Beans.java:76)
看来必须得给一个参数为空的默认构建器才行呀~
初次学习cglib,总结下下:
1. 对于被代理的类可以声明为abstract,cglib会帮你实现abstract方法,这个看起来很智能呀,呵呵。。。后续再看个究竟;
2. 对于被代理的类,必须要给出一个参数为空的构建器(即默认的constractor);
3. 该默认的constractor建议不要声明为private,毕竟,按照刚刚的方式来操作是会抛Error的哦;
对于第3点,把samples.Beans放在samples.Bean里面作为一个内部类,不知会是啥情况呀,呵呵。。。有点晚了,明儿再试试看~睡觉去罗
分享到:
相关推荐
AOP-CGLIB学习-实现简单的注解权限系统
cglib实现动态代理所依赖的jar包 在学习spring中会用到
JDK动态代理必须提供接口才能使用,在一些不能提供接口的环境中,只能采用其他第三方技术,比如CGLIB动态代理,这里提供CGLIB动态代理的相关jar包,供学习和测试使用。
NULL 博文链接:https://whp0731.iteye.com/blog/357032
com.springsource.net.sf.cglib-sources-2.2.0.jar
截至2016.11.25 github最新版spring 导入 myclipse/eclipse时缺少的jar包。找了很久不容易,这里分享给诸位一起学习spring的朋友!
主要介绍了Spring如何基于Proxy及cglib实现动态代理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
NULL 博文链接:https://coolszy.iteye.com/blog/540457
免责声明:资料部分来源于合法的互联网渠道收集和整理,部分自己学习积累成果,供大家学习参考与交流。收取的费用仅用于收集和整理资料耗费时间的酬劳。 本人尊重原创作者或出版方,资料版权归原作者或出版方所有,...
spring2.0测试学习所需要的jar
CGLIB代理 通过前面的学习可知,JDK的动态代理用起来非常简单,但它是有局限性的,使用动态代理的对象必须实现一个或多个接口。 那么,如何代理没有实现接口的类? CGLIB代理 CGLIB(Code Generation Library)是一...
通过学习它们的原理和实际应用,您将能够更好地理解和利用Spring AOP来提高您的应用程序的可维护性和可扩展性。 内容亮点: JDK动态代理: 我们将详细介绍JDK动态代理的概念和工作原理。您将了解如何使用Java的...
Proxy 模式学习代码,包括静态代理,动态代理,cglib等
jvm虚拟机源码学习资料 配置jar包:cglib-2.2.2.jar
[Spring]基于Spring框架的Web应用演示(附带cglib工具进行动态代理) [Tomcat7.0]Tomcat7版本安装包 [UltraISO]制作U盘启动盘需要的 [log4j_jar]log4j的支持包 [myAutoLoginWeb]过滤器Filter学习-实现用户的自动...
主要介绍了Java使用JDK与Cglib动态代理技术统一管理日志记录,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
学习springmvc专用,包含 spring.jar、spring-webmvc.jar、commons-logging.jar、cglib-nodep-2.1_3.jar hibernate3.jar、hibernate-jpa-2.0-api-1.0.1.Final.jar、antlr-2.7.6.jar、commons-collections-3.1、dom4...
学习spring所需要的jars c3p0-0.9.1.jar com.springsource.net.sf.cglib-2.2.0.jar com.springsource.org.aopalliance-1.0.0.jar com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar commons-logging-...
第四点:CGLIB动态代理代码实现 第五点:代码演示事务传播行为 第六点:代码演示事务隔离级别 第七点:Bean的循环依赖 第八点:Spring的八大设计模式 第九点:17种注入方案,其他视频讲10种以内。 第十点:Bean的8种...
spring2.5学习PPT 传智博客 01_全面阐释Spring及其各项功能 02_搭建与测试Spring的开发环境 03_编码剖析Spring管理Bean的原理 04_Spring的三种实例化Bean的方式 05_配置Spring管理的bean的作用域 06_Spring...