基于jdk和cglib实现的动态代理

来源:互联网 发布:淘宝店铺地址在哪里看 编辑:程序博客网 时间:2024/06/05 00:24

 1:动态代理概述

        代理:本来应该自己做的事情,请了别人来做,被请的人就是代理对象。
举例:春节回家买票让人代买

动态代理:在程序运行过程中产生的这个对象,而程序运行过程中产生对象其实就是我们刚才反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理

2 jdk的动态代理

在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。

基于jdk的动态代理的实例:

2.1 Student.java 接口类

package com.xidian.proxy;


public interface Student {
public void login();
public void submit();
}

2.2 StudentImpl.java 实现类

package com.xidian.proxy;
public class StudentImp implements Student {
@Override
public void login() {
System.out.println("登录");
}
@Override
public void submit() {
System.out.println("提交");
}
}

2.3 MyProxy.java 代理类:

package com.xidian.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//cjlib的代理是基于继承实现的,jdk是基于接口实现的代理
public class MyProxy implements InvocationHandler{

private Object  targetObject;
public Object createProxyInstance(Object targetObject)
{
this.targetObject = targetObject;
/*
* public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,
* InvocationHandler h)
* 第一个参数是要代理对象的类加载器
* 第二个参数是要代理类的接口
* 第三个参数是InvocationHandler的实现类实例,即就是MyProxy 即this
*/
return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(), 
this.targetObject.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("权限校验");
method.invoke(targetObject, args);//执行被代理target对象的方法
System.out.println("日志记录");
return null;
}

}

2.4 测试类

package com.xidian.proxy;

import org.junit.Test;

public class testProxy {
@Test
public void jdkProxy(){
MyProxy myProxy = new MyProxy();
Student proxy = (Student)myProxy.createProxyInstance(new StudentImp());
proxy.login();
proxy.submit();
}
}

3 cglib实现的动态代理

       CGLIB(CODE GENERLIZE LIBRARY)代理是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的所有方法,所以该类或方法不能声明称final的。

基于cglib的动态代理的实例:

3.1  ClassHasNoInterface.java  实现类:

package com.xidian.CGlib;


public class ClassHasNoInterface {
public void  method(){  
        System.out.println("方法一执行");  
    }  
    public void function(){  
        System.out.println("方法二执行");  
    }  
}

3.2 测试类:

public class testCGLib {
@Test
public void  test1() {
        final ClassHasNoInterface p = new ClassHasNoInterface();
        //返回p的动态代理对象:该代理对象是Person的子类
        ClassHasNoInterface pp = (ClassHasNoInterface)Enhancer.create(p.getClass(), new MethodInterceptor(){
            @Override
            public Object intercept(Object proxy, Method method, Object[] arg2,
                    MethodProxy arg3) throws Throwable {
                long time = System.nanoTime();//纳秒  1毫秒=1000纳秒
                Object obj = method.invoke(p, arg2);
                System.out.println(method.getName()+"运行耗时:"+(System.nanoTime()-time)+"纳秒");
                return obj;
            }     
        });
        
        pp.method();
        pp.function();
}

原理区别:
java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

1 0