您的位置:首页 > 编程语言 > Java开发

jdk动态代理和cglib动态代理小记

2015-09-15 14:48 459 查看
1.代理相关

代理是什么

有一种设计模式就叫做代理模式,说的大概意思是当访问某个对象的时候通过其他一个对象来间接的调用,而直接访问的那个对象就是所谓的代理。

代理就像我们去干一件事情经过的中间人那个角色。

为什么要使用代理

比如我们要访问的对象在远程网络的另一台机器上,那么这个过程可能涉及到网络编程等其他复杂操作,如果有一个代理专门来干这件事情,调用者只需要调用本地的代理就可以了。

代理有哪些

总的来说分为静态代理和动态代理,静态代理就是事先写好代理的代码然后调用,而动态代理则是通过把要代理的类作为参数传入,然后生成代理。动态代理比静态代理更加灵活。

2.两种代理对比

jdk动态代理的使用方法如下

interface ITestClass{
    public void sayHello();
}
class TestClassImp implements ITestClass{
    public void sayHello(){
        System.out.println("hello");
    }
}
public class JDKProxy implements InvocationHandler {
    private Object target;

    /**
     * 绑定委托对象并返回一个代理类
     *
     * @param target
     * @return
     */
    public Object bind(Object target) {
        this.target = target;
        //取得代理对象
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);   //要绑定接口(这是一个缺陷,cglib弥补了这一缺陷)
    }

    @Override
    /**
     * 调用方法
     */
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object result = null;
        System.out.println("事物开始");
        result = method.invoke(target, args);
        System.out.println("事物结束");
        return result;
    }

    public static void main(String args[]) {
        JDKProxy proxy= new JDKProxy();
        //TestClassImp obj = (TestClassImp)proxy.bind(new TestClassImp()); 转型为具体类型报错
        ITestClass obj = (ITestClass)proxy.bind(new TestClassImp());
        obj.sayHello();
    }
}

jdk动态代理在生成代理对象的过程是通过proxy.newproxyinstance来实现的。该函数主要是通过传入的classloader以及接口生成class文件,然后再根据class文件生成生成代理。byte[] proxyClassFile =<span style="white-space:pre"> </span>ProxyGenerator.generateProxyClass(
<span style="white-space:pre"> </span>    proxyName, interfaces);
<span style="white-space:pre"> </span>try {
<span style="white-space:pre"> </span>    proxyClass = defineClass0(loader, proxyName,
<span style="white-space:pre"> </span>proxyClassFile, 0, proxyClassFile.length);
<span style="white-space:pre"> </span>} catch (ClassFormatError e) {
<span style="white-space:pre"> </span>    /*
<span style="white-space:pre"> </span>     * A ClassFormatError here means that (barring bugs in the
<span style="white-space:pre"> </span>     * proxy class generation code) there was some other
<span style="white-space:pre"> </span>     * invalid aspect of the arguments supplied to the proxy
<span style="white-space:pre"> </span>     * class creation (such as virtual machine limitations
<span style="white-space:pre"> </span>     * exceeded).
<span style="white-space:pre"> </span>     */
<span style="white-space:pre"> </span>    throw new IllegalArgumentException(e.toString());
<span style="white-space:pre"> </span>}

cglib代理方法如下
public class CglibProxy implements MethodInterceptor {

private Object target;

public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// 回调方法
// enhancer.setCallbackType(this.getClass());
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
}

@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("before run!");
proxy.invokeSuper(obj, args);
System.out.println("after run!");
return null;
}
public static void main(String args[]){
CglibProxy proxy = new CglibProxy();
TestClassImp objimp = (TestClassImp)proxy.getInstance(new TestClassImp()); //转型为具体实现类也可以执行
ITestClass obj = (ITestClass)proxy.getInstance(new TestClassImp());
obj.sayHello();
objimp.sayHello();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: