昨天写了一段代码,关于在方法中调用动态代理给方法调用者在使用前加入权限校验和使用后加入日志记录功能。简化如下
public class UserDaoImpl implements UserDao { //用户类
@Override //重写各种方法
public void add() {
System.out.println("添加功能");
}
@Override
public void delete() {
System.out.println("删除功能");
}
@Override
public void update() {
System.out.println("修改功能");
}
@Override
public void find() {
System.out.println("查找功能");
}
}
public class MyInvocationHandler implements InvocationHandler { //自己创建实现InvocationHandler接口的类
private Object target=null;
public MyInvocationHandler(Object target) { //构造方法中传入目标方法
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("权限校验");
Object result = method.invoke(target, args);
System.out.println("日志生成");
return result;
}
}
public class UserDaoTest {
public static void main(String[] args) {
InvocationHandler handler = new MyInvocationHandler(udi);
UserDao newUdi = (UserDao) Proxy.newProxyInstance(udi.getClass().getClassLoader(), udi.getClass().getInterfaces(), handler);
newUdi.add();
newUdi.delete();
newUdi.update();
newUdi.find();
}
}
第三块运行后显示的接结果如下:
可见使用动态代理已经通过InvocationHandler的invoke方法把传入的Method对象进行了编织。但是
UserDao newUdi = (UserDao) Proxy.newProxyInstance(udi.getClass().getClassLoader(), udi.getClass().getInterfaces(), handler);
这一句代码理解起来有难度,但是可以转换成
Proxy.getProxyClass(udi.getClass().getClassLoader(), udi.getClass().getInterfaces()).getConstructor(new Class[] { InvocationHandler.class }).newInstance(new Object[] { handler });
就比较好理解了。
这种方法的局限性是编织的对象要实现同一个接口,否则动态代理需要使用第三方库使用。