Java动态代理解析

xiaoxiao2021-02-28  91

1.最原始的代码

package com.tansen.shop.test.proxy; public interface Dao { void insert(); void update(); void delete(); } package com.tansen.shop.test.proxy; public class DaoImpl implements Dao { @Override public void insert() { System.out.println("DaoImpl.insert()"); } @Override public void update() { System.out.println("DaoImpl.update()"); } @Override public void delete() { System.out.println("DaoImpl.delete()"); } }

2.我现在要给insert和update加上执行时间的日志 没有动态代理会怎么样?

package com.tansen.shop.test.proxy; public class LogDao implements Dao{ Dao dao = new DaoImpl(); @Override public void insert() { System.out.println("insert执行开始时间"+System.currentTimeMillis()); dao.insert(); System.out.println("insert执行结束时间"+System.currentTimeMillis()); } @Override public void update() { System.out.println("--------------------------------------------"); dao.update(); } @Override public void delete() { System.out.println("--------------------------------------------"); System.out.println("insert执行开始时间"+System.currentTimeMillis()); dao.delete(); System.out.println("insert执行结束时间"+System.currentTimeMillis()); } }

缺点: 方法调用前后输出时间的逻辑无法复用,如果有别的地方要增加这段逻辑就得再写一遍 如果Dao有其它实现类,那么必须新增一个类去包装该实现类,这将导致类数量不断膨胀

使用代理模式

package com.tansen.shop.test.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class ProxyDao implements InvocationHandler { private Object obj; public ProxyDao(Object obj) { this.obj = obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); if ("insert".equals(methodName) || "update".equals(methodName)) { System.out.println(methodName + "()方法开始时间:" + System.currentTimeMillis()); Object result = method.invoke(obj, args); System.out.println(methodName + "()方法结束时间:" + System.currentTimeMillis()); return result; } return method.invoke(obj, args); } }

调用

package com.tansen.shop.test.proxy; import java.lang.reflect.Proxy; public class Test { public static void main(String[] args) { Dao dao = new DaoImpl(); Dao proxyDao = (Dao) Proxy.newProxyInstance(ProxyDao.class.getClassLoader(),new Class<?>[] {Dao.class},new ProxyDao(dao)); proxyDao.insert(); System.out.println("==========分割线==========="); proxyDao.delete(); System.out.println("==========分割线==========="); proxyDao.update(); } }

结果

insert()方法开始时间:1513246731570 DaoImpl.insert() insert()方法结束时间:1513246731571 ==========分割线=========== DaoImpl.delete() ==========分割线=========== update()方法开始时间:1513246731571 DaoImpl.update() update()方法结束时间:1513246731571

优点: 1.输出日志的逻辑被复用起来,如果要针对其他接口用上输出日志的逻辑,只要在newProxyInstance的时候的第二个参数增加Class<?>数组中的内容即可。

缺点 这种方式的缺点为: 1.JDK提供的动态代理只能针对接口做代理,不能针对类做代理 2.代码依然有耦合,如果要对delete方法调用前后打印时间,得在LogInvocationHandler中增加delete方法的判断

参照:http://www.cnblogs.com/xrq730/p/7003082.html

转载请注明原文地址: https://www.6miu.com/read-76150.html

最新回复(0)