http://www.cnblogs.com/frankliiu-java/articles/1896443.html
示例代码:
public interface AopService {
public void doService();
}
public class AopServiceImpl implements AopService {
private String singal;
public String getSingal() {
return singal;
}
public AopServiceImpl(){}
public AopServiceImpl(String singal){
this.singal = singal;
}
@Override
public void doService() {
System.out.println("do service method is being invoked now!!!");
}
}
public class ProxyFactory implements InvocationHandler {
private Object targetObject;
public Object createTargetObject(Object targetObject){
this.targetObject = targetObject;
return Proxy.newProxyInstance(this.targetObject.getClass()
.getClassLoader(),
this.targetObject.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object arg0, Method method, Object[] args)
throws Throwable {
AopServiceImpl aopservice = (AopServiceImpl)this.targetObject;
Object result = null;
if(aopservice.getSingal()!=null){
result = method.invoke(targetObject, args);
}
return result;
}
}
测试代码:
public class AopTests {
@Test
public void Tests(){
ProxyFactory pf = new ProxyFactory();
//AopService as = (AopService)pf.createTargetObject(new AopServiceImpl());
AopService as = (AopService)pf.createTargetObject(new AopServiceImpl("Frank"));
as.doService();
}
}
JDK动态代理为什么必须用接口以及与CGLIB的对比
这两天对AOP原理感兴趣了,试验了JDK动态代理与CGLIB动态代理。从Spring的AOP框架介绍中得知对于使用接口的类,Spring使用JDK动态代理(原来做项目中试图从Bean强制转换为实现类,结果报错,原来是这么回事),没有接口的就使用别的AOP框架aspectj,但这些都是依赖于Java字节码工具ASM生成一个原类的新类,调用Callback
但是JDK动态代理为什么必须使用接口一直很疑惑,难道原理不是像ASM一样修改字节码吗?带着这个疑问,开始看JDK的Proxy代码。使用JDK动态代理的代码代码
ITestBean tb = (ITestBean) Proxy.newProxyInstance(tb.getClass().getClassLoader(), tb.getClass().getInterfaces(), new TestBeanHander(tb));
于是从创建代理函数看起,即public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces, InvocationHandler h)
throws IllegalArgumentException ,
通过源码可以看到,这个类第一步生成一个代理类(注意,这里的参数就是接口列表),
Class cl = getProxyClass(loader, interfaces);
然后通过代理类找到构造参数为InvocationHandler的构造函数并生成一个新类。
Constructor cons = cl.getConstructor(constructorParams);//这个有用,在后面细说
return (Object) cons.newInstance(new Object[] { h });
接口起什么作用呢,于是又看getProxyClass方法的代码,这个源码很长,就不细说了。大致分为三段:
第一:验证
第二:缓存创建新类的结构,如果创建过,则直接返回。(注意:这里的KEY就是接口列表)
第三:如果没有创建过,则创建新类
创建代码如下
long num;
//获得代理类数字标识
synchronized (nextUniqueNumberLock) {
num = nextUniqueNumber++;
}
//获得创建新类的类名$Proxy,包名为接口包名,但需要注意的是,如果有两个接口而且不在同一个包下,也会报错
String proxyName = proxyPkg + proxyClassNamePrefix + num;
//调用class处理文件生成类的字节码,根据接口列表创建一个新类,这个类为代理类,
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces);
//通过JNI接口,将Class字节码文件定义一个新类
proxyClass = defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
根据前面的代码Constructor cons = cl.getConstructor(constructorParams);
可以猜测到接口创建的新类proxyClassFile 不管采用什么接口,都是以下结构
public class $Proxy1 extends Proxy implements 传入的接口{
}
生成新类的看不到源代码,不过猜测它的执行原理很有可能是如果类是Proxy的子类,则调用InvocationHandler进行方法的Invoke
到现在大家都应该明白了吧,JDK动态代理的原理是根据定义好的规则,用传入的接口创建一个新类,这就是为什么采用动态代理时为什么只能用接口引用指向代理,而不能用传入的类引用执行动态类。
cglib采用的是用创建一个继承实现类的子类,用asm库动态修改子类的代码来实现的,所以可以用传入的类引用执行代理类
JDK动态代理与CGLIB对比如下:
//JDK动态代理测试代码
补充说明,如果在实现类中,接口定义的方法互相调用不会在调用InvocationHandler的invoke方法,JDK动态代理应该不是嵌入到Java的反射机制中,而是在反射机制上的一个调用。
分享到:
相关推荐
NULL 博文链接:https://jummy.iteye.com/blog/255628
java代理机制 JDK动态代理和cglib代理 详解
java静态代理 jdk动态代理 cglib动态代理 代理原理
jdk 的动态代理和CGLIB代理
jdk 和 cglib的简单动态代理,闲来无事 写写。有需要的朋友可以看看
AOP之JDK动态代理和CGLib动态代理 ,具体效果和过程看博文 http://blog.csdn.net/evankaka/article/details/45195383
Spring框架的AOP中重要的一个知识点,动态代理,springAOP框架会根绝实际情况选择使用jdk的动态代理还是cglib的动态代理
实现java动态代理的两个实例,jdk动态代理和cglib
JAVA动态代理实现Demo(JDK动态代理和CGLIB动态代理)
jdk和cglib动态代理的例子{jar包+源码} 解压:如有问题 用快压
JDK动态代理,关于jdk动态代理的问题!详细的说明!JDK动态代理JDK动态代理
静态代理、jdk动态代理、cglib动态代理
JDK代理和Cglib代理,下载源码清楚了解二者区别
JAVA JDK静态代理、动态代理、CGlib代理的代码演示 为对象增加功能
代理模式详解-jdk与cglib动态代理与底层实现,spring中常用的设计模式,本案例是从源码到代理模式的实现。
动态代理是使用jdk的反射机制,创建对象的...jdk动态代理,必须有接口,目标类必须实现接口, 没有接口时,需要使用cglib动态代理。 动态代理可以在不改变原来目标方法功能的前提下, 可以在代理中增强自己的功能代码。
jdk动态代理与cglib动态度代理的区别原理代码jar包
JDK动态代理和Cglib动态代理实例源码
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类...
CGLIB代理 通过前面的学习可知,JDK的动态代理用起来非常简单,但它是有局限性的,使用动态代理的对象必须实现一个或多个接口。 那么,如何代理没有实现接口的类? CGLIB代理 CGLIB(Code Generation Library)是一...