代理模式
代理模式
- 一个类拥有另一个类的功能。
介绍
意图:
- 为类提供一种代理以控制对这个类的访问
使用场景:
- 访问一个类时想做一些访问控制
关键代码
- 目标类和代理类相结合
优点:
- 保护目标对象
- 扩展性高
- 职责清晰
缺点:
- 处理速度变慢
- 实现可能会比较复杂
注意:
- 与装饰器模式区别:
1.侧重于访问控制
2.侧重于自己增加功能
使用
- 静态代理
/**
* 具体功能
* @author 98543
*/
public interface Func {
public void work();
public void eat();
}
/**
* 具体对象
* @author 98543
*/
public class Targer implements Func{
@Override
public void eat() {
System.out.println("走啊,去吃饭");
}
@Override
public void work() {
System.out.println("走啊,去工作");
}
}
/**
* 代理对象
* @author 98543
*/
public class Worker implements Func{
private Targer laozong;
private Vistor vistor;
public Worker(Targer laozong,Vistor vistor) {
this.laozong = laozong;
this.vistor = vistor;
}
@Override
public void eat() {
System.out.println(vistor.getName()+"约老总去吃饭了");
laozong.eat();
System.out.println("他想 ->"+vistor.getWhat());
}
@Override
public void work() {
System.out.println(vistor.getName()+"约老总去工作了");
laozong.work();
System.out.println("他想 ->"+vistor.getWhat());
}
}
// 静态代理
Vistor vistor = new Vistor("张三","目的很纯粹啊");
Targer MrLi = new Targer();
Worker wk = new Worker(MrLi, vistor);
wk.eat();
wk.work();
// 输出
张三约老总去吃饭了
走啊,去吃饭
他想 ->目的很纯粹啊
张三约老总去工作了
走啊,去工作
他想 ->目的很纯粹啊
- jdk动态代理
/**
* 具体功能
* @author 98543
*/
public interface Func {
public void work();
public void eat();
}
/**
* 具体对象
* @author 98543
*/
public class Targer implements Func{
@Override
public void eat() {
System.out.println("走啊,去吃饭");
}
@Override
public void work() {
System.out.println("走啊,去工作");
}
}
/**
* 代理对象
* @author 98543
*/
public class Doctor implements InvocationHandler{
private Targer laozong;
public Doctor(Targer laozong) {
this.laozong = laozong;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("1");
Object obj = method.invoke(laozong, args);
System.out.println("2");
return obj;
}
}
// jdk动态代理
Doctor doctor = new Doctor(MrLi);
Func func = (Func) Proxy.newProxyInstance(Vistor.class.getClassLoader(), new Class[] {Func.class}, doctor);
func.eat();
// 输出
1
走啊,去吃饭
2
- cglib动态代理
/**
* 具体对象
* @author 98543
*/
public class CglibTarget {
public void drink() {
System.out.println("百事可乐");
}
}
// 代理类
public class CglibProxy implements MethodInterceptor{
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
System.out.println("第一步");
Object obj = arg3.invokeSuper(arg0, arg2);
System.out.println("第二步");
return obj;
}
}
// cglib动态代理(无需实现接口)
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Sample.class);
enhancer.setCallback(new CglibProxy());
Sample sample = (Sample) enhancer.create();
sample.eat();
// 输出
第一步
yaxiyalei
第二步
jdk:
基于反射,效率较慢,只能基于接口实现代理。
cglib(注意jar包冲突问题):
基于字节码,依赖于asm库,无需实现也可代理,使用继承实现代理,会生成一个子类,所以不能对final修饰的方法或类进行代理。