jdk动态代理和cglib动态代理

jdk动态代理

  1. 实现
    a、 一个接口
    b、 一个接口的实现类
    c、 一个动态代理类
    只能实现接口的动态代理,通过proxy.NewProxyInstance来动态创建一个代理对象这个代理对象实现了这个接口并且继承了proxy类。
    最后只会创建一个类文件
package proxy;
 
public interface Star
{
    String sing(String name);
    
    String dance(String name);
}
package proxy;
 
public class LiuDeHua implements Star
{   
    @Override
    public String sing(String name)
    {
         System.out.println("给我一杯忘情水");
 
        return "唱完" ;
    }
    
    @Override
    public String dance(String name)
    {
        System.out.println("开心的马骝");
 
        return "跳完" ;
    }
}

package proxy;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
 
public class StarProxy implements InvocationHandler
{
    // 目标类,也就是被代理对象
    private Object target;
    
    public void setTarget(Object target)
    {
        this.target = target;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    {
        // 这里可以做增强
        System.out.println("收钱");
        
        Object result = method.invoke(target, args);
        
        return result;
    }
    
    // 生成代理类
    public Object CreatProxyedObj()
    {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }  
   
}

package proxy;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
 
public class StarProxy implements InvocationHandler
{
    // 目标类,也就是被代理对象
    private Object target;
    
    public void setTarget(Object target)
    {
        this.target = target;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    {
        // 这里可以做增强
        System.out.println("收钱");
        
        Object result = method.invoke(target, args);
        
        return result;
    }
    
    // 生成代理类
    public Object CreatProxyedObj()
    {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }  
   
}
  1. 核心类
    proxy类
    invocationHandler接口
    在代理类调用方法时会动态生成一个实现了被代理的接口的实现类

Cglib动态代理

final修饰的类cglib无法进行动态代理,因为fianl修饰的类时不可边的,不能有子类的实现
通过可以继承的父类所有的公开方法,然后可以重写这些方法,在重写这些方法增强,这就时cglib的思想

最后会创建三个类文件,其中一个是当前被代理类的子类,两个是继承了FastClass类的子类在这里插入图片描述

package proxy;
 
import java.lang.reflect.Method;
 
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
 
public class CglibProxy implements MethodInterceptor
{
   /** CGLib需要代理的目标对象 */
    private Object target;

    //相当于JDK动态代理中的绑定
    public Object getInstance(Object target) {
	    //给业务对象赋值
        this.target = target;  
        //创建加强器,用来创建动态代理类
        Enhancer enhancer = new Enhancer(); 
        //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
        enhancer.setSuperclass(this.target.getClass());  
        //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
        enhancer.setCallback(this);
        // 创建动态代理类对象并返回
        return enhancer.create();
    }
    // 实现回调方法
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("预处理——————");
        proxy.invokeSuper(obj, args); //调用业务类(父类中)的方法
        System.out.println("调用后操作——————");
        return null;
    }
}
调用》》》》》》》》》》》》》》》》》》》》》》
   public static void main(String[] args)
    {
        int times = 1000000;
        
        Star ldh = new LiuDeHua();
        StarProxy proxy = new StarProxy();
        proxy.setTarget(ldh);
        
        long time1 = System.currentTimeMillis();
        Star star = (Star)proxy.CreatProxyedObj();
        long time2 = System.currentTimeMillis();
        System.out.println("jdk创建时间:" + (time2 - time1));
        
        CglibProxy proxy2 = new CglibProxy();
        long time5 = System.currentTimeMillis();
        Star star2 = (Star)proxy2.CreatProxyedObj(LiuDeHua.class);
        long time6 = System.currentTimeMillis();
        System.out.println("cglib创建时间:" + (time6 - time5));
        
        long time3 = System.currentTimeMillis();
        for (int i = 1; i <= times; i++)
        {
            star.sing("ss");
            
            star.dance("ss");
        }
        long time4 = System.currentTimeMillis();
        System.out.println("jdk执行时间" + (time4 - time3));
        
        long time7 = System.currentTimeMillis();
        for (int i = 1; i <= times; i++)
        {
            star2.sing("ss");
            
            star2.dance("ss");
        }
        
        long time8 = System.currentTimeMillis();
        
        System.out.println("cglib执行时间" + (time8 - time7));   
    }

cglib和jdk代理对比

1、使用情况不一样,jdk代理只有在代理对象有实现的接口时才能使用,cglib可以直接代理没有实现接口的对象
2、cglib是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理(asm是什么文末有解释),jdk动态代理时利用拦截器加上反射机制生成一个代理接口的匿名类。
3、JDK动态代理只能对实现了接口的类生成代理,而不能针对类。CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,并覆盖其中方法实现增强,但是因为采用的是继承,所以该类或方法最好不要声明成final,对于final类或方法,是无法继承的。
4、1)使用CGLib实现动态代理,CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,
5、在jdk6之前比使用Java反射效率要高。在jdk6、jdk7、jdk8逐步对JDK动态代理优化之后,在调用次数较少的情况下,JDK代理效率高于CGLIB代理效率,只有当进行大量调用的时候,jdk6和jdk7比CGLIB代理效率低一点,但是到jdk8的时候,jdk代理效率高于CGLIB代理,
6、唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。

asm是什么
ASM是一个java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性以及 Java 字节码(指令)。ASM从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。

binary name 是什么
提供为任何类名String在ClassLoader参数的方法必须是The Java™ Language Specification所定义的二进制名称。

有效的类名的示例包括:

   "java.lang.String"
   "javax.swing.JSpinner$DefaultEditor"
   "java.security.KeyStore$Builder$FileBuilder$1"
   "java.net.URLClassLoader$3$1"
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值