本文共 3613 字,大约阅读时间需要 12 分钟。
代理是一种常见的设计模式,旨在在不修改源代码的情况下对目标类的方法进行增强或扩展。在Java中,代理可以分为静态代理和动态代理两种形式。本文将重点介绍动态代理的实现方式及其应用场景。
动态代理通过Proxy.newProxyInstance方法来创建接口代理对象。该方法的三个主要参数如下:
通过InvocationHandler,我们可以在不修改目标类源代码的情况下,动态地增强目标类的方法行为。
假设我们有一个接口OneDao,其中定义了一个方法add(int a, int b)用于计算两个整数的和。以下是接口的定义:
public interface OneDao { public int add(int a, int b);} 接下来,我们创建一个实现OneDao接口的类OneDaoImpl。该类的实现如下:
public class OneDaoImpl implements OneDao { @Override public int add(int a, int b) { return a + b; }} 为了实现动态代理,我们需要定义一个InvocationHandler的实现类MyHandler。该类将负责动态地处理被代理方法的调用。以下是MyHandler的实现:
class MyHandler implements InvocationHandler { private Object object; // 被代理对象 public MyHandler(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("方法前:" + method.getName()); Object result = method.invoke(object, args); System.out.println("方法后:" + method.getName()); return result; }} 通过Proxy.newProxyInstance方法,我们可以根据指定的接口和调用处理器创建一个动态代理对象。以下是创建代理对象的代码示例:
@Testpublic void method() { OneDaoImpl oneDao = new OneDaoImpl(); OneDao dao = (OneDao) Proxy.newProxyInstance(OneDaoImpl.class.getClassLoader(), new Class[]{OneDaoImpl.class}, new MyHandler(oneDao) ); int add = dao.add(1, 2); System.out.println(add);} 通过上述代码,我们可以看到动态代理对象dao实际上是通过MyHandler来调用OneDaoImpl类的方法。每当调用dao.add(1, 2)时,MyHandler都会先输出日志,执行目标方法oneDao.add(1, 2),然后再输出日志。
动态代理的主要优势在于它能够在不修改目标类源代码的情况下,动态地增强目标类的方法行为。这种特性在以下场景尤为有用:
假设我们有一个Human接口,定义了两个方法getAge()和getName()。我们可以通过动态代理来增强这些方法的行为。
public class GDPeople implements Human { private int age; private String name; public GDPeople(int age, String name) { this.age = age; this.name = name; } @Override public int getAge() { return age; } @Override public String getName() { return name; }} 我们可以创建一个ProxyFactory工厂类,用于生成动态代理对象。以下是ProxyFactory的实现:
public class ProxyFactory { public static Object getProxyInstance(Object obj) { MyInvocationHandler handler = new MyInvocationHandler(); handler.bind(obj); return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler ); }}class MyInvocationHandler implements InvocationHandler { private Object object; public void bind(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("代理之前:" + method.getName()); Object result = method.invoke(object, args); System.out.println("代理之后:" + method.getName()); return result; }} public class ProxyTest { public static void main(String[] args) { GDPeople gdPeople = new GDPeople(15, "Tom"); Human proxyInstance = (Human) ProxyFactory.getProxyInstance(gdPeople); int age = proxyInstance.getAge(); String name = proxyInstance.getName(); System.out.println("name:" + name + "-----age:" + age); }} 运行上述代码,输出结果如下:
name:Tom-----age:15
通过本文的详细分析和代码示例,我们可以看到动态代理是一种强大的设计模式,能够在不修改目标类源代码的情况下,动态地增强目标类的方法行为。在实际应用中,动态代理广泛应用于日志记录、性能监控、安全性验证等场景。
转载地址:http://chca.baihongyu.com/