java动态代理与静态代理的区别

2022-10-04 08:17:09 浏览数 (1)

一、静态代理

静态代理的代理类和被代理类有一个相同的接口:

接口:

代码语言:javascript复制
public interface HelloInterface {
    void sayHello();
    void sayNo(String no);
    String callYes(int number,String yes);
}

被代理类:

代码语言:javascript复制
public class Hello implements HelloInterface{
    
    @Override
    public void sayHello() {
        System.out.println("Hello zhanghao!");
    }

    @Override
    public void sayNo(String no) {
    }

    @Override
    public String callYes(int number, String yes) {
        Log.i("ProxyHandler", "Hello callYes "   number   " "   yes);
        return "yes";
    }
}

代理类:

代码语言:javascript复制
public class HelloProxy implements HelloInterface{

    private HelloInterface helloInterface;

    public HelloProxy(HelloInterface helloInterface){
        this.helloInterface = helloInterface;
    }

    @Override
    public void sayHello() {
        System.out.println("Before invoke sayHello" );
        helloInterface.sayHello();
        System.out.println("After invoke sayHello");
    }

    @Override
    public void sayNo(String no) {
        System.out.println("Before invoke sayHello" );
        helloInterface.sayNo(no);
        System.out.println("After invoke sayHello");
    }

    @Override
    public String callYes(int number, String yes) {
        System.out.println("Before invoke sayHello" );
        return helloInterface.callYes(number, yes);
    }
}

使用静态代理:

代码语言:javascript复制
public static void call() {
        HelloProxy helloProxy = new HelloProxy(new Hello());

        helloProxy.sayHello();
        helloProxy.sayNo("no");
        helloProxy.callYes(1, "yes");
    }

静态代理的优点: 如果是相同接口下的被代理类,可以使用同一个代理类。

静态代理的缺点: 但如果是不同接口的被代理类,则需要再写一个冗长代理类。 另外代理类中需要实现所有被代理类的方法。

二、动态代理

动态代理则弥补了上述静态代理的缺点: 1、如果换不同的接口的被代理类,不用再写一个冗长的代理类,Proxy.newProxyInstance()出来一个代理类就可以。

2、代理类不用实现所有的被代理的方法,一个InvocationHandler 的 invoke() 方法中使用method.invoke(object, args)可以实现。

例如:

代码语言:javascript复制
public class ProxyHandler implements InvocationHandler {

    private Object object;

    public ProxyHandler(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String argss = "null";
        if(args != null){
            argss = args[0].toString();
        }
        Log.i("ProxyHandler", "Before invoke  "   object.getClass().getSimpleName()
                  " "   method.getName()   "  "   argss);
        method.invoke(object, args);
        return null;
    }
}

动态代理对上述Hello.java的调用:

代码语言:javascript复制
public static void remoteHello() {

        HelloInterface hello = new Hello();

        HelloInterface helloProxy = (HelloInterface) Proxy.newProxyInstance(
                hello.getClass().getClassLoader(), hello.getClass().getInterfaces(),
                new ProxyHandler(hello));

        helloProxy.sayHello();
        helloProxy.sayNo("no");
        helloProxy.callYes(1, "s");
    }

例如,再代理一个PersonInterface,不用再写代理类:

代码语言:javascript复制
public interface PersonInterface {
    void getName();
    void setColor(String color);
    String doString(int number, String yes);
}

被代理类如下Person.java :

代码语言:javascript复制
public class Person implements PersonInterface {

    @Override
    public void getName() {
    }

    @Override
    public void setColor(String color) {
    }

    @Override
    public String doString(int number, String yes) {
        Log.i("ProxyHandler", "Person doString "   number   " "   yes);
        return null;
    }
}

调用时如下所示:

代码语言:javascript复制
public static void remotePerson() {

        PersonInterface person = new Person();
        PersonInterface personProxy = (PersonInterface) Proxy.newProxyInstance(
                person.getClass().getClassLoader(), person.getClass().getInterfaces(),
                new ProxyHandler(person));

        personProxy.getName();
        personProxy.setColor("s");
        personProxy.doString(1, "d");
    }

动态代理的优势: 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。 想想你有100个静态代理类,现在有一个需求,每个代理类都需要新增一个处理逻辑,你需要打开100个代理类在每个代理方法里面新增处理逻辑吗? 有或者代理类有5个方法,每个方法都需要新增一个处理逻辑, 你需要在每个方法都手动新增处理逻辑吗? 想想就挺无趣的。动态代理类帮你一键搞定。

动态代理的缺点: 1、JDK动态代理需要业务实现类所实现的接口。如果业务实现类是没有实现接口而是直接定义业务方法的话,就无法使用JDK动态代理了。(JDK动态代理重要特点是代理接口) 并且,如果业务实现类中新增了接口中没有的方法,这些方法是无法被代理的(因为无法被调用)。动态代理只能对接口产生代理,不能对类产生代理。

0 人点赞