代理模式是基本的设计模式之一,它是开发者为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象。这些操作通常涉及与“实际”对象的通信,因此代理通常充当着中间人的角色。
Java动态代理实现机制采用了反射的思想,有关于反射的基础知识,可以参见博客Java发射机制浅析。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
下面演示两个简单的示例:方法性能监测和日志管理
实体类
public class User { private String name; public User(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
接口
public interface UserDao { void addUser(User user); void deleteUser(String name); void updateUser(String name); }
实现类
public class UserDaoImpl implements UserDao { @Override public void addUser(User user) { System.out.println("add user named " + user.getName() + "..."); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public void deleteUser(String name) { System.out.println("delete user named " + name + "..."); try { Thread.sleep(1500); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public void updateUser(String name) { System.out.println("update user named " + name + "..."); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } }
InvocationHandler实现类
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class PerformanceInterceptor implements InvocationHandler { private Object proxied; public PerformanceInterceptor(Object proxied) { this.proxied = proxied; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long startTime = System.currentTimeMillis(); Object obj = method.invoke(proxied, args); long endTime = System.currentTimeMillis(); System.out.println("Method " + method.getName() + " execution time: " + (endTime - startTime) * 1.0 / 1000 + "s"); return obj; } }
测试类
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import org.junit.Test; public class PerformanceInterceptorTest { @Test public void testInvoke() { UserDao userDao = new UserDaoImpl(); Class<?> cls = userDao.getClass(); InvocationHandler handler = new PerformanceInterceptor(userDao); UserDao proxy = (UserDao) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), handler); proxy.addUser(new User("tom")); proxy.deleteUser("tom"); proxy.updateUser("tom"); } }
测试结果
add user named Tom... Method addUser execution time: 1.0s delete user named tom... Method deleteUser execution time: 1.5s update user named tom... Method updateUser execution time: 2.0s
有时候开发者需要在方法开始执行和执行结束时打印一些信息,使用动态代理就可以对所有方法或者某些方法进行简单日志管理,并写入到指定文件。
InvocationHandler实现类
import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.text.DateFormat; import java.text.SimpleDateFormat; public class LogInterceptor implements InvocationHandler { private Object proxied; public static final String path = "run.log"; public LogInterceptor(Object proxied) { this.proxied = proxied; } public String beforeMethod(Method method) { return getFormatedTime() + " Method:" + method.getName() + " start running/r/n"; } public String afterMethod(Method method) { return getFormatedTime() + " Method:" + method.getName() + " end running/r/n"; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { write(path, beforeMethod(method)); Object object = method.invoke(proxied, args); write(path, afterMethod(method)); return object; } public String getFormatedTime() { DateFormat formater = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); return formater.format(System.currentTimeMillis()); } public void write(String path, String content) { FileWriter writer = null; try { writer = new FileWriter(new File(path), true); writer.write(content); writer.flush(); } catch (IOException e) { e.printStackTrace(); } finally { if(null != writer) { try { writer.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
测试类
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import org.junit.Test; public class LogInterceptorTest { @Test public void testInvoke() { UserDao userDao = new UserDaoImpl(); Class<?> cls = userDao.getClass(); InvocationHandler handler = new LogInterceptor(userDao); UserDao proxy = (UserDao) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), handler); proxy.addUser(new User("tom")); proxy.deleteUser("tom"); proxy.updateUser("tom"); } }
测试结果
在工程根目录下生成run.log文件,内容如下:
2015-10-07 05:41:02 Method:addUser start running 2015-10-07 05:41:03 Method:addUser end running 2015-10-07 05:41:03 Method:deleteUser start running 2015-10-07 05:41:05 Method:deleteUser end running 2015-10-07 05:41:05 Method:updateUser start running 2015-10-07 05:41:07 Method:updateUser end running