Java动态代理机制介绍(jdk和cglib的区别)
2017-09-23 23:12
495 查看
原理区别:
Java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
具体区别代码分析jdk和cglib原理:
Jdk动态代理:Proxy.newProxyInstance(classLoader, interfaces, InvocationHandler)
要在classLoader里去找interfaces,如果也加载进来了才能继续执行,并且用ProxyGenerator动态生成了一个代理类的字节码文件(使用了缓存技术,只需要生成一次),然后用classLoader将这个字节码文件加载进来。这就是classLoader的作用。
现在举一个例子 :JDK的动态代理是基于 接口的,我们首先创建一个接口Court.java,定义一个打官司的方法 。具体代码如下:
定义一个Person类Person.java
最后创建一个测试类TestDemo.java
我们想代理这个对象必须需要实现方法拦截器接口MethodInterceptor,创建CglibPerson.java,代码如下:
最后我们看效果吧!就直接写一个主方法来测试了,DemoCglib.java如下:
程序执行的结果是:
你家里有背景,你脸白!!
打官司———-!
Java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
具体区别代码分析jdk和cglib原理:
Jdk动态代理:Proxy.newProxyInstance(classLoader, interfaces, InvocationHandler)
要在classLoader里去找interfaces,如果也加载进来了才能继续执行,并且用ProxyGenerator动态生成了一个代理类的字节码文件(使用了缓存技术,只需要生成一次),然后用classLoader将这个字节码文件加载进来。这就是classLoader的作用。
现在举一个例子 :JDK的动态代理是基于 接口的,我们首先创建一个接口Court.java,定义一个打官司的方法 。具体代码如下:
public interface Court { void doCourt(); }
定义一个Person类Person.java
public class People implements Court{ private String name; public People() { super(); // TODO Auto-generated constructor stub } public People(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void doCourt() { // TODO Auto-generated method stub System.out.println("我是"+name+"我没有犯罪"); } }
最后创建一个测试类TestDemo.java
package com.yida.ProxyDemo; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import org.junit.Test; public class TestDemo { /** * jdk提供的动态代理是基于接口实现的,给接口的所有 * 实现类生产代理对象 */ @Test public void test01(){ final Court c = new People("张三");//匿名内部类不能访问外部类方法中的局部变量,除非该变量被声明为final类型 Object oc = Proxy.newProxyInstance(//得到代理对象 TestDemo.class.getClassLoader(), //应用类加载器都可以 c.getClass().getInterfaces(),//被代理对象所有类的实现类 new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub String name = method.getName(); System.out.println(name); if(name.equals("doCourt")){ System.out.println("视频表明,事发当时张三在优衣库,不可能犯罪"); return method.invoke(c, args); }else{ return method.invoke(c, args); } } }); Court cc = (Court) oc; cc.doCourt(); cc.toString(); } } 输出结果为: <img src="https://img-blog.csdn.net/20170923232008295?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGlrZW1lYmVl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" width="30%" height="auto" alt=""/> 好像图片不好使,直接把地址复制到地址栏回车就可以看到了,这里我就复制下结果吧! 结果是: doCourt 视频表明,事发当时张三在优衣库,不可能犯罪 我是张三我没有犯罪 toString cglib动态代理更加灵活,这里直接演示基于类的代理方法 。 首先有一个Person类Person.java,定义了一个打官司的方法doCourt,代码如下:
package com.yida.cglib; public class Person { public void doCourt(){ System.out.println("打官司----------"); } }
我们想代理这个对象必须需要实现方法拦截器接口MethodInterceptor,创建CglibPerson.java,代码如下:
package com.yida.cglib; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /** * 实现接口: 方法拦截器 * 1.在执行person里面的方法时,执行流程,首先找方法拦截器, * 执行拦截器的方法 * person.doCourt()方法----->拦截器的方法:intercept()方法 * 2.在这里通过EnHanser对象去给Person生成代理对象 * */ @SuppressWarnings("all")//先去除所有黄线警告 public class CglibPerson implements MethodInterceptor{ //创建enhanser对象 public Enhancer en = new Enhancer(); //给person生成代理对象 public Object getProxy(Class clazz){// Person.class //引入父类:Person ,生成代理对象不就是Person的子类(子类就是代理对象) en.setSuperclass(clazz); en.setCallback(this); //得到了代理对象 Object obj = en.create(); return obj; } /** * 参数1 : 类对象,person * 参数2 : 类里面的方法对象,doCourt方法对象 * 参数3: args 方法里面的参数 * 参数4: 代理方法对象 * MethodProxy@e582a85: * methodProxy: 代理对象的方法,而不是执行父类的Person的方法method */ public Object intercept(Object obj , Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("你家里有背景,你脸白!!"); //Object obj1 = method.invoke(obj,args); //返回的代理对象 Object obj1 = methodProxy.invokeSuper(obj, args);// method.invoke(obj,args); return obj1; } }
最后我们看效果吧!就直接写一个主方法来测试了,DemoCglib.java如下:
package com.yida.cglib; /** * p代理对象: null * 在拦截方法里面: * * 不执行这个方法:method.invoke(obj,args);而是: methodProxy.invokeSuper(obj, args); * 代理对象: Person$$EnhancerByCGLIB$$45cef45a@48b49e4 * 代理对象就是Person的子类 * @author Administrator * */ public class DemoCglib { public static void main(String[] args) { //1.得到代理对象 CglibPerson cp = new CglibPerson(); // proxy : Object proxy = cp.getProxy(Person.class); //2.类型转换 //cn.itheima.cg.Person$$EnhancerByCGLIB$$45cef45a@48b49e4 Person p = (Person) proxy; //System.out.println(p); p.doCourt(); } }
程序执行的结果是:
你家里有背景,你脸白!!
打官司———-!
相关文章推荐
- Java动态代理机制详解(JDK动态代理与CGLIB动态代理区别)
- Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)
- Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)
- Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)
- Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)
- Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)
- Java基础-jdk动态代理与cglib动态代理区别
- Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)
- Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)
- Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM) (清晰,浅显)
- Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)
- Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)
- Java动态代理模式jdk和cglib的2种实现以及二者的区别(AOP面向切面的前奏)
- Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)
- 【转载】Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)
- Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)
- Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM) (清晰,浅显)
- Java动态代理机制原理详解(JDK 和CGLIB,Javassist,ASM)
- Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)
- Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)