Java学习:动态代理的一点小理解
Posted _acct
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java学习:动态代理的一点小理解相关的知识,希望对你有一定的参考价值。
手动实现
之前的一篇讲IoC的博文提到了代理模式,事实上代理模式就是AOP实现的重要基石。但是上面的代码有一个显而易见的缺陷,也就是之前讲解反射内容时提到的:不具备动态性。
上面代码中的Server就像是反射理解博文中提到的工厂订单管理员一样,每增加一样菜系,就需要相应更新手上的菜单。类比反射特性,我们完全可以做到让服务员不需要手上拿着菜单来为顾客服务:
// 服务员实现类
public class ServerImpl implements Server {
// 采用组合的方式引入noodles
private Noodles noodles;
@Override
public void getNoodles() {
// 代理模式
noodles.getNoodles();
}
// 利用反射特性
@Override
public void setNoodles(String noodles) {
this.noodles = (Noodles) Class.forName(noodles).newInstance();
}
}
}
API实现
之前的动态代理是我们手动实现的,JDK其实自带了很多实现动态代理的类和方法。可能初次接触时会显得有些复杂,所以先画一张图来表示我们整个的设计思路:
之前在讨论IoC举的餐馆用例中,除了不具备动态性之外还有一个缺陷:服务员只服务于本餐馆,也就是说,我们能不能把服务员这个群体抽离出来,不仅服务这个餐馆,也能服务于多家餐馆,以实现代码的复用呢?
现实生活中有一种类型的公司,叫做家政公司,我们可以类比来编写一个服务员工厂:
public class ServerFactory implements InvocationHandler {
private Object target;
// 设定服务对象
public void setTarget(Object target) {
this.target = target;
}
// 返回具体的服务团队
public Object getServer() {
return Proxy.newProxyInstance(
this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
// 这一部分代码暂时忽略不管
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(target, args);
}
}
这是利用java.lang.reflect包提供的动态代理相关类和方法编写的ServerFactory。最后的invoke方法是继承接口要求的重写方法,不妨碍我们理解,暂时忽略,主要关注前半部分的代码。
前半部分代码非常好理解:
- 工厂接到业务需求:给某某提供服务。派出服务团队
- 利用setTarget确定服务对象。
- 使用getServer返回对应的服务人员。
下面使用这个类进行测试,同样以与餐馆厨师对接为例:
public class ServerTest {
public static void main(String[] args) {
// 获取服务员团队
ServerFactory serverGroup = new ServerFactory();
// 设定该团队对接面食厨师
serverGroup.setCooker(new NoodleCooker());
// 获取单个服务员
Cooker server = (Cooker) serverGroup.getServer();
// 顾客点餐
server.cooking();
}
}
// NoodleCooker类
public class NoodleCooker implements Cooker {
@Override
public void cooking() {
System.out.println("开始下面了!");
}
}
// Cooker接口
public interface Cooker {
void cooking();
}
我们实现了服务员和餐馆之间的解耦。有了服务员工厂,可以给任意的客户提供专业服务团队(setTarget),并且为每一次服务需求提供单个服务员进行实现(getServer)。
以上是关于Java学习:动态代理的一点小理解的主要内容,如果未能解决你的问题,请参考以下文章