代理模式之Java动态代理实现方法
代理模式是一种常见的设计模式,它允许使用代理对象来控制对某个对象的访问。代理对象通常维护着对真正对象的引用,并在访问时进行特定的处理,例如对对象方法的调用进行拦截或增强。Java动态代理是一种强大的实现代理模式的方法,它基于Java反射机制,可以在运行时动态地生成代理类,无需手动创建代理类,非常灵活。
下面我们来看一下Java动态代理的实现方法。
Java动态代理的实现方法
Java动态代理通过以下步骤来实现代理对象的动态生成:
1.定义一个接口或父类
首先,我们需要定义一个接口或父类,作为真正对象和代理对象的共同接口。
public interface Hello {
void sayHello();
}
2.实现InvocationHandler接口
接着,我们需要实现Java提供的InvocationHandler接口,该接口定义了一个invoke方法,用于处理代理对象的方法调用。在该方法中,我们可以对方法调用进行拦截和增强。
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before say hello");
Object result = method.invoke(target, args);
System.out.println("after say hello");
return result;
}
}
3.生成代理对象
最后,我们可以使用Java提供的Proxy类的newProxyInstance方法来生成代理对象。该方法接收三个参数:ClassLoader对象、Class数组和InvocationHandler对象。其中,ClassLoader对象用于加载生成的代理类,Class数组用于指定需要代理的接口或父类,InvocationHandler对象用于处理代理对象的方法调用。
public class Main {
public static void main(String[] args) {
Hello hello = new HelloImpl();
MyInvocationHandler handler = new MyInvocationHandler(hello);
Hello proxy = (Hello) Proxy.newProxyInstance(hello.getClass().getClassLoader(), hello.getClass().getInterfaces(), handler);
proxy.sayHello();
}
}
运行上述代码,我们可以看到输出如下:
before say hello
hello world
after say hello
可以发现,在方法调用前后,我们分别输出了before say hello和after say hello,证明代理类的方法调用已被成功拦截和增强。
示例说明
下面,我们通过两个示例来说明Java动态代理的实现方法。
示例1:计算器
假设我们有一个计算器接口,定义了加、减、乘、除四个方法。我们希望使用代理类来记录每次操作的时间戳。
首先,我们定义计算器接口:
public interface Calculator {
int add(int a, int b);
int sub(int a, int b);
int mul(int a, int b);
int div(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;
}
@Override
public int mul(int a, int b) {
return a * b;
}
@Override
public int div(int a, int b) {
return a / b;
}
}
接着,我们实现一个代理类,用于处理计算器操作的时间戳:
public class CalculatorProxy implements InvocationHandler {
private Object target;
public CalculatorProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("start " + method.getName() + " at " + new Date());
Object result = method.invoke(target, args);
System.out.println("end " + method.getName() + " at " + new Date());
return result;
}
}
最后,我们可以使用以下代码来使用代理类:
Calculator calculator = new CalculatorImpl();
Calculator proxy = (Calculator) Proxy.newProxyInstance(calculator.getClass().getClassLoader(), calculator.getClass().getInterfaces(), new CalculatorProxy(calculator));
System.out.println(proxy.add(1, 1));
System.out.println(proxy.sub(10, 8));
System.out.println(proxy.mul(3, 4));
System.out.println(proxy.div(8, 2));
运行上述代码,我们可以看到输出如下:
start add at Thu Jul 01 12:01:40 CST 2021
2
end add at Thu Jul 01 12:01:40 CST 2021
start sub at Thu Jul 01 12:01:40 CST 2021
2
end sub at Thu Jul 01 12:01:40 CST 2021
start mul at Thu Jul 01 12:01:40 CST 2021
12
end mul at Thu Jul 01 12:01:40 CST 2021
start div at Thu Jul 01 12:01:40 CST 2021
4
end div at Thu Jul 01 12:01:40 CST 2021
我们可以发现,代理类成功地记录了每次操作的时间戳。
示例2:动态生成类
我们可以通过Java动态代理,在运行时动态地生成一个类,并使用该类实现接口中的方法。
首先,我们定义一个接口和一个实现该接口的类:
public interface Animal {
void say();
}
public class Dog implements Animal {
@Override
public void say() {
System.out.println("wang wang");
}
}
然后,我们可以使用Java动态代理来实现该接口:
Animal animal = (Animal) Proxy.newProxyInstance(Animal.class.getClassLoader(), new Class<?>[] { Animal.class }, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before say");
Object result = method.invoke(new Dog(), args);
System.out.println("after say");
return result;
}
});
animal.say();
运行上述代码,我们可以看到输出如下:
before say
wang wang
after say
我们可以发现,代理类成功地实现了接口,并对实现方法进行了拦截和增强。由于使用动态代理生成的代理类是在运行时动态生成的,仅在运行期间可用,非常灵活和方便。
至此,我们已经详细讲解了Java动态代理的实现方法,希望对您有所帮助。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:代理模式之Java动态代理实现方法 - Python技术站