什么是Java动态代理?

  • Post category:Java

Java动态代理是一种在运行时生成代理对象的技术,它可以无需编写具体的代理类代码,通过一组接口和实现类,动态的生成相应的代理类,从而实现对目标对象的代理操作。使用动态代理,可以在不修改原有类的前提下,对类的某些方法进行增强或者加入其他的逻辑。

下面是Java动态代理的使用攻略,包含以下步骤:

第一步:编写接口

首先,需要编写一个接口类,该接口类包含原有类的方法以及需要动态代理处理的方法。

public interface People {
    void eat();
    void sleep();
    void work();
    void study();
    void play();
}

第二步:编写目标类

接着,需要编写目标类,该类实现上面的接口,并实现其中的方法。

public class PeopleImpl implements People {
    @Override
    public void eat() {
        System.out.println("eat...");
    }

    @Override
    public void sleep() {
        System.out.println("sleep...");
    }

    @Override
    public void work() {
        System.out.println("work...");
    }

    @Override
    public void study() {
        System.out.println("study...");
    }

    @Override
    public void play() {
        System.out.println("play...");
    }
}

第三步:编写代理类

接下来,需要编写代理类,在代理类中,我们需要实现InvocationHandler接口,并重写其中的invoke()方法。在该方法中,我们可以调用原有类中的方法,也可以对该方法进行增强或加入其他逻辑。

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

public class PeopleProxy implements InvocationHandler {
    private Object target;

    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理类执行方法:" + method.getName());

        Object result = method.invoke(target, args);

        System.out.println("方法执行结束");
        return result;
    }  
}

第四步:使用代理类

最后,我们需要使用代理类来完成对目标类的代理操作。

public class Test {
    public static void main(String[] args) {
        People people = new PeopleImpl();
        PeopleProxy proxy = new PeopleProxy();
        People peopleProxy = (People)proxy.bind(people);

        peopleProxy.eat();
        peopleProxy.sleep();
        peopleProxy.study();
    }
}

在上述代码中,我们首先实例化了原有类PeopleImpl和代理类PeopleProxy。接着,我们通过代理类的bind()方法获取到代理对象peopleProxy。最后,在使用代理对象的方法时,代理类的invoke()方法就会被调用,从而实现了对原有类方法的代理。在这里,我们对代理类的invoke()方法进行了增强,在原有方法执行前后输出一些字符串。

示例2:

public interface Calculator {
    int add(int a, int b);
    int sub(int a, int b);
}

public class CalculatorImpl implements Calculator {
    @Override
    public int add(int a, int b) {
        return a + b;
    }

    @Override
    public int sub(int a, int b) {
        return a - b;
    }
}

public class CalculatorProxy implements InvocationHandler {
    private Object target;

    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理类执行方法:" + method.getName() + "(" + args[0] + "," + args[1] + ")");

        Object result = method.invoke(target, args);

        System.out.println("方法执行结束,结果为:" + result);
        return result;
    }
}

public class Test {
    public static void main(String[] args) {
        Calculator calculator = new CalculatorImpl();
        CalculatorProxy proxy = new CalculatorProxy();
        Calculator calculatorProxy = (Calculator)proxy.bind(calculator);

        int a = 10, b = 5;
        int res1 = calculatorProxy.add(a, b);
        int res2 = calculatorProxy.sub(a, b);

        System.out.println("计算结果 res1:" + res1);
        System.out.println("计算结果 res2:" + res2);
    }
}

在这个示例中,我们使用了另一个接口Calculator和实现类CalculatorImpl,使用代理类CalculatorProxy对CalculatorImpl进行了代理操作。在代理类中,我们使用了反射技术和动态代理生成了代理对象,并在该对象的方法中增加了输出字符串的操作。在最后的代码中,我们对代理对象的方法进行了多次调用,以便验证代理类Proxy的效果。

综上所述,Java动态代理是一种在运行时生成代理对象的技术,可以在不修改原有类的前提下,对类的某些方法进行增强或者加入其他的逻辑。