代理模式
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。为其他对象提供一种代理以控制对这个对象的访问。
主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
关键代码:增加中间层,实现与被代理类组合。
优点:
1、职责清晰。 2、高扩展性。 3、智能化。
缺点:
1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
注意事项:
1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。
2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。
代码实现
首先创建公共接口和被代理对象实体
//公共接口
public interface Rent {
void renting();
}
//被代理对象
public class Corey implements Rent {
//这是被代理对象!(房主)
@Override
public void renting() {
System.out.println("Corey有房出租");
}
}
1.静态代理
代理对象实例
//代理对象(中介)
public class StaticProxyRent implements Rent {
private Rent rent;
public StaticProxyRent(Rent rent){
this.rent = rent;
}
@Override
public void renting() {
System.out.println("向房客出租房屋");
this.rent.renting();
System.out.println("完成售后服务");
}
}
测试
public class Main {
public static void main(String[] args) {
Rent rent = new Corey();
StaticProxyRent staticProxyRent = new StaticProxyRent(rent);
staticProxyRent.renting();
}
}
2.动态代理
JDK动态代理
newProxyInstance:生成代理对象Proxy
asm:通过操作字节码,生成Proxy$0文件
XXXX.getClassLoader():负责把磁盘上的.class
文件加载到JVM内存中
XXXX.getInterfaces():获得这个对象所实现的所有接口
InvocationHandler():自行编译需要的代理功能
invoke(Object proxy, Method method, Object[] args):proxy是代理对象本身,method是被代理的方法,args是代理方法的参数。
代理对象实例
//代理对象(中介)
//动态生成代理对象的工厂
public class JdkProxyFactory {
public static void before(){
System.out.println("带领房客看房...签租房协议");
}
public static void after(){
System.out.println("售后服务");
}
//动态生成代理对象
public static Object getProxyBean(Object target){
Class clazz = target.getClass();
//在JDK中动态生成代理对象的方法
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {
//动态生成代理对象的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object obj = method.invoke(target,args);
after();
return obj;
}
});
}
}
测试
public class Main {
public static void main(String[] args) {
Rent jdkProxyRent = new Corey();
Rent jdkProxyRent1 =(Rent)JdkProxyFactory.getProxyBean(jdkProxyRent);
jdkProxyRent1.renting();
}
}
Cglib动态代理
enhancer 成为被代理类的子类,假如类为final则不能使用Cglib实现代理。
代理对象实例
public class CglibProxyBeanFactory {
public static Object getProxyBean(Rent rent){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(rent.getClass());
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("带领客户看房,签订租房协议");
Object obj = method.invoke(rent,objects);
System.out.println("售后服务");
return obj;
}
});
return enhancer.create();
}
}
测试
public class Main {
public static void main(String[] args) {
Rent rent = new Corey();
Rent rent1 = (Rent) CglibProxyBeanFactory.getProxyBean(rent);
rent1.renting();
}
}