博主专注于Java、架构、Linux、小程序、爬虫、自动化等技术。 工作期间含泪整理出一些资料,微信搜索【程序员高手之路】,回复 【java】【黑客】【爬虫】【小程序】【面试】等关键字免费获取资料
前言
先赞后看,此生必赚!
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;
}
}
解读:
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),由他判断是否有权限,调用者只需要调用,实现自己的逻辑,不关心权限问题。