欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java静态代理、动态代理

程序员文章站 2022-06-09 21:40:21
...

一、代理
代理模式:就是为其他对象提供一种代理以控制对这个对象的访问。
代理可以在不改动目标对象的基础上,增加其他额外的功能(扩展功能)。

举个例子来说明代理的作用:
一般我们想邀请明星来当我们的代言人,我们并不能直接联系到明星,而是通过其经纪人,来告诉经纪人我们需要和明星进行合作,然后通过经纪人来转达给明星。,明星只需要做好代言工作就好,其他繁琐的事情就交于经纪人就可以。这里的经经纪人就是一个代理对象,明星就是一个目标对象

二、静态代理

静态代理在使用时,需要定义接口或者父类,被代理对象(目标对象)与代理对象(Proxy)一起实现相同的接口或者是继承相同父类。

1.创建动作主题(定义一个接口)

package com.imp4m.reflex.proxy;


/**
 * 主题(动作、行为)
 */
public interface Subject {

    /**购物*/
    public void shopping();
}

2.创建一个动作执行实例

package com.imp4m.reflex.proxy;

/**
 * 实现类、决定完成动作的最后一步
 */
public class Person implements Subject,Order{

    /**
     * 完成付款
     */
    @Override
    public void shopping() {
        System.out.println("付款了。完成购物");
    }
}

3.创建代理对象

package com.imp4m.reflex.proxy;

public class StaticProxy {

    private Subject target;

    public StaticProxy(Subject target) {
        this.target = target;
    }

    public void doAction(){
        System.out.println("挑选商品中。。。");
        System.out.println("完成商品挑选。");
        target.shopping();
    }
}

4.静态代理测试

package com.imp4m.reflex.proxy;

import org.junit.Test;

public class ProxyTest {

    @Test
    public void staticProxyTest(){

        Subject subject = new Person();
        StaticProxy staticProxy = new StaticProxy(subject);
        staticProxy.doAction();
    }
}

总结:静态代理可以达到在不改变被代理对象的动作的前提下来扩展新的功能。

可以实现在不修改目标对象的基础上,对目标对象的功能进行扩展。但是由于代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护,可以使用动态代理方式来解决。

三、动态代理
动态代理有以下特点:

1.代理对象,不需要实现接口
2.代理对象的生成,是利用JDK的API,动态的在内存中创建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)
3.动态代理也叫做:JDK代理,接口代理

1).创建动态代理对象

package com.imp4m.reflex.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


/**
 * 用于动态生成代理对象
 */
public class CreateProxy implements InvocationHandler {

    private Object target;//被代理的对象,如:Subject

    /**
     * 用于创建代理对象
     * @return
     */
    public Object create(Object target){
       this.target = target;
        Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                this);
        return proxy;
    }

    /**
     * 代理对象的执行方法
     * @param object 代理对象类
     * @param method 被代理对象的方法
     * @param args 被代理对象的方法的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object object, Method method, Object[] args) throws Throwable {
        System.out.println("挑选商品中。。。");
        System.out.println("完成商品挑选。。。");
        method.invoke(target,args);
        return null;
    }
}

2).动态代理测试

package com.imp4m.reflex.proxy;

import org.junit.Test;

public class ProxyTest {

    @Test
    public void proxyTest(){
        Person person = new Person();
        CreateProxy createProxy = new CreateProxy();
        Subject proxy = (Subject) createProxy.create(person);
        proxy.shopping();
    }
}

动态代理实现过程:

  1. 通过getProxyClass0()生成代理类。JDK生成的最终真正的代理类,它继承自Proxy并实现了我们定义的接口.

  2. 通过Proxy.newProxyInstance()生成代理类的实例对象,创建对象时传入InvocationHandler类型的实例。

  3. 调用新实例的方法,即此例中的save(),即原InvocationHandler类中的invoke()方法。

注意:代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理
另提供参考地址:https://www.cnblogs.com/linzhong/p/7234051.html