前言
先赞后看,此生必赚!
Java中动态代理的实现,主要是InvocationHandler和Proxy的使用。
可以通过以下步骤实现一个动态代理:
一、创建正常的接口以及实现类
1. 接口:
public interface People { public void working(); }
2. 实现类:
public class Student implements People { @Override public void work() { System.out.println("正在学习..."); } }
二、创建一个PeopleHandler实现InvocationHandler
public class PeopleHandler implements InvocationHandler { private Object obj; public PeopleHandler(Object obj) { this.obj = obj; } public Object getProxy(Object obj) { return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before invoke..."); Object result = method.invoke(obj, args); System.out.println("after invoke..."); return result; } }u
解读:
PeopleHandler(Object obj):通过被代理对象创建handler;
getProxy(Object obj):通过被代理对象创建代理;
invoke(Object proxy, Method method, Object[] args):代理不直接调用invoke,而是使用正常的方法时都会走invoke方法;
三、调用方法
可以使用两种方式调用方法:
1. 直接调用
不使用代理类直接调用,直接实现业务逻辑
2. 使用代理类调用
使用代理类调用,间接实现业务逻辑
public class TestProxy { public static void main(String[] args) { //1.直接调用 System.out.println("直接调用:"); People people = new Student(); people.work(); //2.通过代理调用 System.out.println("\n通过代理调用:"); PeopleHandler handler = new PeopleHandler(people); People proxy = (People) handler.getProxy(people); proxy.work(); } }
结果:
直接调用: 正在学习... 通过代理调用: before invoke... 正在学习... after invoke...
四、总结
1. 使用代理的好处
从上面的案例可以看出,两者都可以实现正常的业务逻辑,那为啥要多此一举地使用代理类呢?
1.1 降低耦合度
正常逻辑work()与日志的关系没那么强烈,可以对业务逻辑的各个部分进行隔离。
1.2 提高可重用性
如果不使用代理,需要每一次在调用work()前后都要写日志,这样的话,代码的可重用性为0!
使用代理之后,只需要在handler的invoke()方法中写一次即可,重用性明显提高!
2. 使用场景
除了上面案例中的日志,还有性能统计,安全控制,事务处理,异常处理等等。
安全控制举例:
校验用户权限,每一个菜单请求,都要判断一下请求的用户是否有该菜单权限。菜单多了,代码冗余,且容易遗漏。
通过动态代理就可以实现为:每一个用户,每一个菜单的请求,都经过代理(proxy),由他判断是否有权限,调用者只需要调用,实现自己的逻辑,不关心权限问题。