ck代理商鹏卫齐商业(ck代理商有五折吗)

这节我们来看一个非常重要的设计模式——代理模式,尽管我们工作中可能很少用到,但它是很多框架重要功能的基石,肘,我们开始吧。

引言

节假日的地铁站,你是否见过有人掏出电脑,原地输出,原来是群里被疯狂@……

告诉自己不准哭

用户提问题,客服@我们解决,可能很多开发同学都经历过这样的场景。

用户找到客服,提出问题,客服又找到开发同学,让开发同学去解决问题,开发同学解决完,最后反馈给客服,客服再反馈到用户。

站在用户的视角,感觉就是客服解决了这个问题,这其实就是一种代理。

用户向客服提问题

我们以这个例子,来看看Java怎么实现代理模式的吧。

Java的三种代理模式实现

代理模式的定义:

Provide a surrogate or placeholder for another object to control access to it.(为其他对象提供一种代理以控制对这个对象的访问。)

简单说,就是设置一个中间代理来控制访问原目标对象,达到增强原对象的功能和简化访问方式的目的。

代理模式通用类图

Java实现代理模式分为两类三种,两类是静态代理动态代理,动态代理又可以分为JDK动态代理CGLib动态代理

Java实现代理模式

静态代理

静态代理比较简单,代理类需要实现和目标接口类一样的接口。

Solver静态代理类图

public interface ISolver {
void solve();
}
Solverpublic class Solver implements ISolver {
@Override
public void solve() {
System.out.println("疯狂掉头发解决问题……");
}
}
public class SolverProxy implements ISolver {
//目标对象
private ISolver target;

public SolverProxy(ISolver target) {
this.target = target;
}

@Override
public void solve() {
System.out.println("请问有什么能帮到您?");
target.solve();
System.out.println("问题已经解决啦!");
}
}
public class Client {
public static void main(String[] args) {
//目标对象:程序员
ISolver developer = new Solver();
//代理:客服小姐姐
SolverProxy csProxy = new SolverProxy(developer);
//目标方法:解决问题
csProxy.solve();
}
}
请问有什么能帮到您?
疯狂掉头发解决问题……
问题已经解决啦!

我们看到,通过静态代理,可以在不修改目标对象的前提下扩展目标对象的功能。

但是,它也有一些问题:

JDK动态代理

JDK动态代理利用了JDK反射机制,动态地在内存中构建代理对象,从而实现对目标对象的代理功能。

它主要用到了两个反射类的API:

我们来看看使用JDK动态代理之后的客服代理场景。

JDK动态代理类图

public interface ISolver {
void solve();
}
public class Solver implements ISolver {
@Override
public void solve() {
System.out.println("疯狂掉头发解决问题……");
}
}
public class ProxyFactory {

// 维护一个目标对象
private Object target;

public ProxyFactory(Object target) {
this.target = target;
}

// 为目标对象生成代理对象
public Object getProxyInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("请问有什么可以帮到您?");

// 调用目标对象方法
Object returnValue = method.invoke(target, args);

System.out.println("问题已经解决啦!");
return null;
}
});
}
}
public class Client {
public static void main(String[] args) {
//目标对象:程序员
ISolver developer = new Solver();
//代理:客服小姐姐
ISolver csProxy = (ISolver) new ProxyFactory(developer).getProxyInstance();
//目标方法:解决问题
csProxy.solve();
}
}
请问有什么可以帮到您?
疯狂掉头发解决问题……
问题已经解决啦!

我们简单总结一下静态代理和动态代理的主要区别:

静态代理动态代理最主要区别

我们也观察到,JDK动态代理,目标对象必须得实现接口,也就是说它是面向接口的,假如我们不想要接口怎么办呢?

Cglib动态代理

CGLIB(Code Generation Library)是一个基于ASM的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成,它是通过继承来实现的。

我们来看看使用Cglib之后,我们的客服代理是什么样的:

Cglib动态代理类图

 <dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.5</version>
</dependency>
public class Solver {

public void solve() {
System.out.println("疯狂掉头发解决问题……");
}
}
public class ProxyFactory implements MethodInterceptor {

//维护一个目标对象
private Object target;

public ProxyFactory(Object target) {
this.target = target;
}

//为目标对象生成代理对象
public Object getProxyInstance() {
//工具类
Enhancer en = new Enhancer();
//设置父类
en.setSuperclass(target.getClass());
//设置回调函数
en.setCallback(this);
//创建子类对象代理
return en.create();
}

@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("请问有什么可以帮到您?");
// 执行目标对象的方法
Object returnValue = method.invoke(target, args);
System.out.println("问题已经解决啦!");
return null;
}

}
Clientpublic class Client {
public static void main(String[] args) {
//目标对象:程序员
Solver developer = new Solver();
//代理:客服小姐姐
Solver csProxy = (Solver) new ProxyFactory(developer).getProxyInstance();
//目标方法:解决问题
csProxy.solve();
}
}
请问有什么可以帮到您?
疯狂掉头发解决问题……
问题已经解决啦!

我们可以看到Cglib动态代理和JDK动态代理最大的区别就是:

我们还需要注意:

扩展:动态代理的应用

标题里说了,开源框架都在用的代理模式,那么主流的开源框架哪些地方用到了代理模式呢?——确切说是动态代理呢?

比如:

原文链接:https://mp.weixin.qq.com/s/aZtfwik0weJN5JzYc-JxYg