在代理模式(Proxy Pattern)中,一个类代表另一个类的功能
意图: 为其他对象提供一种代理以控制对这个对象的访问
主要解决: 在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
何时使用: 想在访问一个类时做一些控制
应用实例: 1、Windows 里面的快捷方式。2、买火车票不一定在火车站买,也可以去代售点。3、一张支票或银行存单是账户中资金的代理。支票在市场交易中用来代替现金,并提供对签发人账号上资金的控制
优点: 1、职责清晰。 2、高扩展性。 3、智能化。
缺点: 1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。 2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
使用场景: 按职责来划分,通常有以下使用场景: 1、远程代理。 2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。 5、Cache代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理。
注意事项: 代理模式是为了加以控制。 比如框架的AOP 日志 数据库请求异常回滚 …
直接上代码 ,看完在总结
//代理接口
public interface Subject {
//代理的方法
public void doSomething();
}
//委托类
public class RealSubject implements Subject {
@Override
public void doSomething() {
System.out.println( "我是被代理的方法" );
}
}
//代理类
public class SubjectProxy implements Subject {
private Subject subimpl = new RealSubject();
@Override
public void doSomething() {//实现AOP
System.out.println("前切面");
subimpl.doSomething();
System.out.println("后切面");
}
}
public class Test {
@org.junit.Test
public void show(){
Subject subject=new SubjectProxy();
subject.doSomething();
}
}
结果:
前切面我是被代理的方法
后切面
public class Test {
@org.junit.Test
public void show(){
Subject subject=new SubjectProxy();
subject.doSomething();
}
}
发现问题了吗 ?
代理类和委托类实现了相同的接口,也就是说代理类和委托类实现了相同的方法。而且一个(代理接口和代理类) 只能代理1个委托类
因为代理类就一个代理方法 已经被一个委托类占用了 就没有方法来代理其他的类了.
如果多个类需要代理的话 那么你就要定义多个代理接口和代理类, 这样就会出现了大量的代码重复。 因为你需要保证代理的方法名称和委托类的方法名称相同 只有这样在调用的时候方法才不会弄错
如果 1万个类的话 是不是很就很困难了 ,这时候动态代理出来了
动态代理是调用Proxy的newProxyInstance方法可以生成代理对象 ,来实现代理的
只能代理实现了接口的类,而没有实现接口的类就不能实现动态代理
先看代码
//接口
public interface Subject {
public void doSomething();
}
//委托类
public class RealSubject implements Subject {
@Override
public void doSomething() {
System.out.println( "我是被代理的方法" );
}
}
重点
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//代理类 固定写法
public class ProxyHandler implements InvocationHandler {
private Object tar;
private static ProxyHandler proxy =null;
public synchronized static ProxyHandler getProxy() {
if (proxy==null){
proxy=new ProxyHandler();
}
return proxy;
}
//绑定委托对象,并返回代理类
public Object bind(Object tar) {
this.tar = tar;
//绑定该类实现的所有接口,取得代理类
ClassLoader classLoader = tar.getClass().getClassLoader();//类加载器。
Class<?>[] interfaces = tar.getClass().getInterfaces();//对象所有接口
return Proxy.newProxyInstance(classLoader, interfaces ,this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
//这里就可以进行所谓的AOP编程了 比如调用方法前记录日志功能.
// 在调用具体函数方法前,执行功能处理
System.out.println("动态代理前切面");
result = method.invoke(tar, args);
//在调用具体函数方法后,执行功能处理
System.out.println("动态代理后切面");
return result;
}
}
public class Test{
@Test
public void show_dl(){
Subject sub =(Subject) ProxyHandler.getProxy().bind(new RealSubject());
sub.doSomething();
}
}
前切面
我是被代理的方法
后切面
注意使用动态代码必须有接口 他是通过接口来找到 继承接口类的方法的
总结:
动态代理 : 代理那些 通用的事件 所有类 都通用 的 (日志 ,异常结构…)
而静态代理: 代理那些特殊类需要 单独处理 或者是 需要动态代理事件的同时还需要别的事件
这时候肯定不能在动态代理里 添加事件 否则全部动态代理 的类都会受影响
方式1 :如果不需要动态代理 里的事件那么给委托类 写一个静态代理就行了
上面有代码这里就不写了
方式2:如果需要动态代理 里的事件 那么就将动态代理和静态代理组合一下就行了
//接口
public interface Subject {
public void doSomething();//需要代理的方法
}
//委托类
public class RealSubject implements Subject {
//重写需要代理的方法
@Override
public void doSomething() {
System.out.println( "我是被代理的方法" );
}
}
//创建一个 静态代理类 继承同一个接口
//代理类
public class SubjectProxy implements Subject {
private Subject subimpl = new RealSubject();
//重写需要代理的方法
@Override
public void doSomething() {//实现AOP
System.out.println("我是静态代理前切面");
subimpl.doSomething();
System.out.println("我是静态代理后切面");
}
}
//省略...ProxyHandler类上面有
//重点强调 传入的对象 不是委托类 而是静态代理类 此时可以把静态代理类当做 委托类就行了
@Test
public void show_dl(){
Subject sub =(Subject) ProxyHandler.getProxy().bind(new SubjectProxy());
sub.doSomething();
}
动态代理前切面
我是静态代理前切面
我是被代理的方法
我是静态代理后切面
动态代理后切面
注意顺序
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/weixin_45203607/article/details/120236521
内容来源于网络,如有侵权,请联系作者删除!