当前位置:首页 » 代理许可 » proxy代理模式

proxy代理模式

发布时间: 2020-12-01 18:33:19

Ⅰ Chrome浏览器怎么设置代理

操作步骤如下:

1、打开浏览器,打开右上角下拉菜单,找到点击打开设置选项:

Ⅱ java设计模式之代理模式:

很简单:对外部提供统一的接口方法,而代理类在接口中实现对真实类的附加操作行为,从而可以在不影响外部调用情况下,进行系统扩展。也就是说,我要修改真实角色的操作的时候,尽量不要修改他,而是在外部在“包”一层进行附加行为,即代理类。

例如:接口A有一个接口方法operator(),真是角色:RealA实现接口A,则必须实现接口方法operator()。客户端Client调用接口A的接口方法operator()。
现在新需求来了,需要修改RealA中的operator()的操作行为。怎么办呢?如果修改RealA就会影响原有系统的稳定性,还要重新测试。这是就需要代理类实现附加行为操作。创建代理ProxyA实现接口A,并将真实对象RealA注入进来。ProxyA实现接口方法operator(),可以增加附加行为,然后调用真实对象的operator()。从而达到了“对修改关闭,对扩展开放”,保证了系统的稳定性。我们看客户端Client调用仍是接口A的接口方法operator(),只不过实例变为了ProxyA类了而已。
建议看看《软件秘笈:设计模式那点事》,当中讲解的很详细,例子也很生动,读了收获很大!希望以上内容对你有帮助!

Ⅲ 编程的Proxy模式,为什么在调用者跟被调用者之间加一个代理类就能降低两个类之间的耦合度

问题:编程的Proxy模式,为什么在调用者跟被调用者之间加一个代理类就能降低两个类回之间的耦合度答?
回答:有了代理类,调用者不必再关心使用的是哪个具体类的服务,所以与具体类的耦合就降低了。当然代理类和具体类之间的耦合是不可能降低的。

Ⅳ 我的浏览器启用了代理服务器,怎么关闭

1、打开IE浏览器,点击右上角图标,点击“工具”,选择下拉中的“Internet选项专”。属

2、在弹出的Internet选项窗口中,点击“连接”,选择“局域网设置”。

3、在弹出的“局域网LAN设置”中,勾去“为LAN使用代理服务器”,点击确定。

通过上述步骤,我们就可以取消掉之前的设置了,不管使用哪个浏览器设置的芝麻代理服务器,都可以通过IE浏览器“设置”下的“Internet选项”来解决问题。

Ⅳ java中的代理模式一般和什么模式相结合

Java编程的目标是实现现实不能完成的,优化现实能够完成的,是一种虚拟技术。生活中的方方面面都可以虚拟到代码中。代理模式所讲的就是现实生活中的这么一个概念:中介。
代理模式的定义:给某一个对象提供一个代理,并由代理对象控制对原对象的引用。
代理模式包含如下角色:
ISubject:抽象主题角色,是一个接口。该接口是对象和它的代理共用的接口。
RealSubject:真实主题角色,是实现抽象主题接口的类。
Proxy:代理角色,内部含有对真实对象RealSubject的引用,从而可以操作真实对象。代理对象提供与真实对象相同的接口,以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
实现动态代理的关键技术是反射。
静态代理
代理模式有几种,虚拟代理,计数代理,远程代理,动态代理。主要分为两类,静态代理和动态代理。静态代理比较简单,是由程序员编写的代理类,并在程序运行前就编译好的,而不是由程序动态产生代理类,这就是所谓的静态。
考虑这样的场景,管理员在网站上执行操作,在生成操作结果的同时需要记录操作日志,这是很常见的。此时就可以使用代理模式,代理模式可以通过聚合和继承两种方式实现:
<pre name="code" class="java">/**方式一:聚合式静态代理 * @author Goser (mailto:[email protected]) * @Since 2016年9月7日 */ //1.抽象主题接口 public interface Manager { void doSomething(); } //2.真实主题类 public class Admin implements Manager { public void doSomething() { System.out.println("Admin do something."); } } //3.以聚合方式实现的代理主题 public class AdminPoly implements Manager{ private Admin admin; public AdminPoly(Admin admin) { super(); this.admin = admin; } public void doSomething() { System.out.println("Log:admin操作开始"); admin.doSomething(); System.out.println("Log:admin操作结束"); } } //4.测试代码 Admin admin = new Admin(); Manager m = new AdminPoly(admin); m.doSomething(); //方式二:继承式静态代理 //与上面的方式仅代理类和测试代码不同 //1.代理类 public class AdminProxy extends Admin { @Override public void doSomething() { System.out.println("Log:admin操作开始"); super.doSomething(); System.out.println("Log:admin操作开始"); } } //2.测试代码 AdminProxy proxy = new AdminProxy(); proxy.doSomething();</pre>
聚合实现方式中代理类聚合了被代理类,且代理类及被代理类都实现了同一个接口,可实现灵活多变。继承式的实现方式则不够灵活。
比如,在管理员操作的同时需要进行权限的处理,操作内容的日志记录,操作后数据的变化三个功能。三个功能的排列组合有6种,也就是说使用继承要编写6个继承了Admin的代理类,而使用聚合,仅需要针对权限的处理、日志记录和数据变化三个功能编写代理类,在业务逻辑中根据具体需求改变代码顺序即可。
动态代理
一般来说,对代理模式而言,一个主题类与一个代理类一一对应,这也是静态代理模式的特点。
但是,也存在这样的情况,有n各主题类,但是代理类中的“前处理、后处理”都是一样的,仅调用主题不同。也就是说,多个主题类对应一个代理类,共享“前处理,后处理”功能,动态调用所需主题,大大减小了程序规模,这就是动态代理模式的特点。
JDK动态代理
实现
<pre name="code" class="java">//1. 抽象主题 public interface Moveable { void move() throws Exception; } //2. 真实主题 public class Car implements Moveable { public void move() throws Exception { Thread.sleep(new Random().nextInt(1000)); System.out.println("汽车行驶中…"); } } //3.事务处理器 public class TimeHandler implements InvocationHandler { private Object target; public TimeHandler(Object target) { super(); this.target = target; } /** * 参数: *proxy 被代理的对象 *method 被代理对象的方法 *args 方法的参数 * 返回: *Object 方法返回值 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long startTime = System.currentTimeMillis(); System.out.println("汽车开始行驶…"); method.invoke(target, args); long stopTime = System.currentTimeMillis(); System.out.println("汽车结束行驶…汽车行驶时间:" + (stopTime - startTime) + "毫秒!"); return null; } } //测试类 public class Test { public static void main(String[] args) throws Exception{ Car car = new Car(); InvocationHandler h = new TimeHandler(car); Class<?> cls = car.getClass(); /** *loader 类加载器 *interfaces 实现接口 *h InvocationHandler */ Moveable m = (Moveable) Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(), h); m.move(); } }</pre>
代码讲解:
在测试代码中,Proxy.newProxyInstance()方法需要3个参数:类加载器(要进行代理的类)、被代理类实现的接口,事务处理器。所以先实例化Car,实例化InvocationHandler的子类TimeHandler,将各参数传入Proxy的静态方法newProxyInstance()即可获得Car的代理类,前面的静态代理,代理类是我们编写好的,而动态代理则不需要我们去编写代理类,是在程序中动态生成的。
JDK动态代理步骤
1. 创建一个实现InvocationHandler接口的类,它必须实现invoke()方法
2. 创建被代理的类及接口
3. 调用Proxy的静态方法,创建一个代理类
4. 通过代理调用方法
而为什么要进行如此操作,可以从Proxy和InvocationHandler的源码中找打答案。对源码不感兴趣的可以将下面的源码部分小节略过。
JDK动态代理原理与源码
ewProxyInstance()方法的源码:
<pre name="code" class="java"> public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException{ if (h == null) { throw new NullPointerException(); } final Class<?>[] intfs = interfaces.clone(); final SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } /*查找或生成指定的代理类*/ Class<?> cl = getProxyClass0(loader, intfs); /*用指定的调用处理程序调用它的构造函数.*/ try { //获得类的构造函数 final Constructor<?> cons =cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) { //当需要代理的类实现了一个非public的接口时,因为这样的接口需要特殊的权限,因此调用doPrivilege(native 修饰的方法)创建代理实例。 return AccessController.doPrivileged(newPrivilegedAction<Object>() { public Object run() { return newInstance(cons,ih); } }); } else { return newInstance(cons,ih); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString()); } }</pre>
可以看到,获得代理类的代码是
Class<?>cl = getProxyClass0(loader,intfs)
并由此获得代理类的构造函数,生成代理类的实例返回给该方法的调用者。
继续跟进getProxyClass0()方法:
<pre name="code" class="java">/** 生成代理类。调用该方法前必须使用checkproxyaccess方法执行权限检查。*/ private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { //检查实现的接口数,65535这个数字好特殊,端口数好像也是这个,这个数字是由虚拟机所决定的,2^16-1个 if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } // 如果代理类已经通过实现给定接口的类加载器创建了,则返回缓存中的该类的副本;否则将通过ProxyClassFactory创建代理类 return proxyClassCache.get(loader, interfaces); }</pre>
还是没有看到代理类是怎么生成的,只知道代理类是从
roxyClassCache
中取得的,这个变量是与缓存相关的一个对象,查看该变量的声明与初始化:
<pre name="code" class="java">private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());</pre>
可以发现
roxyClassCache
是个用来缓存代理类的类变量,大家知道类变量的特点是与类一一对应,在一个虚拟机中类只有一个,对应着在一个虚拟机中类变量也只有一个,且在此处,在Proxy类被加载的时候就赋值了。在赋值操作的参数中有ProxyClassFactory()这么一个构造函数,这个是动态代理中的关键:生成代理类的类文件字节码。继续跟进去,找到代理类的生成之处了:
<pre name="code" class="java"> /** 根据给定的类加载器和接口数组生成代理类的工厂类*/ private static final class ProxyClassFactory implements BiFunction<ClassLoader,Class<?>[], Class<?>> { // 所有代理类名称的前缀 private static final String proxyClassNamePrefix = "$Proxy"; //用于生成唯一代理类名称的下一个序号 private static final AtomicLong nextUniqueNumber = new AtomicLong(); @Override public Class<?> apply(ClassLoader loader,Class<?>[] interfaces) { Map<Class<?>, Boolean>interfaceSet = new IdentityHashMap<>(interfaces.length); for (Class<?> intf : interfaces) { /* 验证类加载器将此接口的名称解析为实际对象的名称。*/ Class<?> interfaceClass =null; try { interfaceClass = Class.forName(intf.getName(),false, loader); } catch (ClassNotFoundException e) { } if (interfaceClass != intf) { throw new IllegalArgumentException( intf + " is not visible from classloader"); } /* 验证类对象确实是一个接口。*/ if (!interfaceClass.isInterface()) { throw new IllegalArgumentException( interfaceClass.getName() + " is not an interface"); } /*确保接口唯一*/ if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) { throw new IllegalArgumentException( "repeated interface: " + interfaceClass.getName()); } } String proxyPkg = null; // 代理类的包名 /*记录非公开代理接口的包,以便将代理类定义在同一个包中。确认所有非公共代理接口都在同一个包中。*/ for (Class<?> intf : interfaces) { int flags = intf.getModifiers(); if (!Modifier.isPublic(flags)) { String name =intf.getName(); int n = name.lastIndexOf('.'); String pkg = ((n == -1) ? "" : name.substring(0, n + 1)); if (proxyPkg == null) { proxyPkg = pkg; } else if (!pkg.equals(proxyPkg)) { throw new IllegalArgumentException( "non-public interfaces fromdifferent packages"); } } } if (proxyPkg == null) { // 如果没有非公开的代理接口,使用com.sun.proxy作为包名 proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; } /* 生成代理类名的序号*/ long num = nextUniqueNumber.getAndIncrement(); //生成全类名 String proxyName = proxyPkg + proxyClassNamePrefix + num; /*生成代理类字节码 */ byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName,interfaces); try { return defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) { throw new IllegalArgumentException(e.toString()); } } }</pre>
ProxyClassFactory
中,可以看到产生代理类的具体逻辑,大致上是,根据传递的被代理类及其实现的接口生成代理类的字节码加载到缓存中,但是加载到缓存中只是一个.java文件也不能用,所以底层还有编译等操作。到这里,可以大致的看清JDK中动态代理的面孔了,实现的步骤为:
1. 创建代理类的源码;
2. 对源码进行编译成字节码;
3. 将字节码加载到内存;
4. 实例化代理类对象并返回给调用者;
底层的代码我们看不到,但是我们可以查看其生成的字节码:
<pre name="code" class="java">//获得字节码的测试方法 byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy1", Car.class.getInterfaces()); FileOutputStream out = null; try { out = new FileOutputStream(System.getProperty("user.dir") + "\\$Proxy1.class"); out.write(classFile); out.flush(); } catch (Exception e) { e.printStackTrace(); } finally { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } //生成的字节码: importcn.com.goser.proxy.imooc.staticproxy.Moveable; importjava.lang.reflect.InvocationHandler; importjava.lang.reflect.Method; importjava.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; public final class $Proxy1 extends Proxy implements Moveable { private static Method m1; private static Method m3; private static Method m0; private static Method m2; public $Proxy1(InvocationHandler paramInvocationHandler) throws { super(paramInvocationHandler); } public final boolean equals(Object paramObject) throws { try { return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue(); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); } public final void move() throws Exception { try { this.h.invoke(this, m3, null); return; } catch (Exception localException) { throw localException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); } public final int hashCode() throws { try { return ((Integer)this.h.invoke(this, m0, null)).intValue(); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); } public final String toString() throws { try { return (String)this.h.invoke(this, m2, null); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m3 = Class.forName("cn.com.goser.proxy.imooc.staticproxy.Moveable").getMethod("move", new Class[0]); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); return; } catch () { throw new NoSuchMethodError(localNoSuchMethodException.getMessage()); } catch () { } throw new NoClassDefFoundError(localClassNotFoundException.getMessage()); } }</pre>
生成的字节码比较长,但是在字节码中最关键的信息是代理类的声明:
ublic final class $Proxy1 extends Proxy
可以看到生成的代理类是继承了Proxy类的,这就是说明了为什么使用JDK动态代理不能实现继承式动态代理,原因是Java不允许多继承,而生成的代理类本身就已经继承了Proxy类。
至此,JDK的动态代理的使用及底层原理分析完毕,揭下动态代理的神秘面纱,果然是枚美女。
至于最底层的native方法是怎么动态生成代理类的字节码我们也可以简单的模拟一下,先分析下模拟的步骤:首先要生成一段代理类的源码,然后将源码编译后生成代理类的实例返回给调用者。依据此步骤开始编写我们的模拟代码:
<pre name="code" class="java">/** * JDK java.lang.reflect.Proxy的模拟 * @author Goser (mailto:[email protected]) * @Since 2016年9月7日 */ public class Proxy { private static final String RT = "\r\n"; public static Object newProxyInstance() throws Exception{ //声明一段源码 String sourceCode = "packagecn.com.goser.proxy.jdk.simulate;"+ RT + "importcn.com.goser.proxy.imooc.staticproxy.Admin;" + RT + "importcn.com.goser.proxy.imooc.staticproxy.Manager;" + RT + "//以聚合方式实现的代理主题" + RT + "public class $Proxy0 implementsManager{" + RT + " privateAdmin admin;" + RT + " public$Proxy0(Admin admin) {" + RT + " super();" + RT + " this.admin= admin;" + RT + " }" + RT + " publicvoid doSomething() {" + RT + " System.out.println(\"Log:admin操作开始\");" + RT + " admin.doSomething();" + RT + " System.out.println(\"Log:admin操作结束\");" + RT + " }" + RT + "}"; String filename = System.getProperty("user.dir") + "/src/main/java/cn/com/goser/proxy/jdk/simulate/$Proxy0.java"; File file = new File(filename); //使用org.apache.commons.io.FileUtils.writeStringToFile()将源码写入磁盘 //编写到处,可以运行一下程序,可以在当前目录中看到生成的.java文件 FileUtils.writeStringToFile(file,sourceCode); //获得当前系统中的编译器 JavaCompiler complier = ToolProvider.getSystemJavaCompiler(); //获得文件管理者 StandardJavaFileManager fileMgr =complier.getStandardFileManager(null, null, null); Iterable its =fileMgr.getJavaFileObjects(filename); //编译任务 CompilationTask task = complier.getTask(null, fileMgr, null, null, null, its); //开始编译,执行完可在当前目录下看到.class文件 task.call(); fileMgr.close(); //load到内存 ClassLoader loader = ClassLoader.getSystemClassLoader(); Class cls = loader.loadClass("cn.com.goser.proxy.jdk.simulate.$Proxy0"); //生成代理类对象 Constructor ct = cls.getConstructor(Admin.class); return ct.newInstance(new Admin()); } } class test{ public static void main(String[] args) throws Exception { Manager m = (Manager)Proxy.newProxyInstance(); m.doSomething(); } }</pre>
运行测试代码,结果和手工编写的结果一致,完成了JDK中动态代理的实现模拟。
cglib动态代理
前面分析到,因为Java只允许单继承,而JDK生成的代理类本身就继承了Proxy类,因此,使用JDK实现的动态代理不能完成继承式的动态代理,但是我们可以使用cglib来实现继承式的动态代理。
大名鼎鼎的Spring中就含有cglib动态代理,在此也以Spring中自带的cglib完成动态代理的实现:
<pre name="code" class="java">//1.具体主题 public class Train{ public void move(){ System.out.println("火车行驶中…"); } } //2.生成代理 public class CGLibProxy implements MethodInterceptor { private Enhancer enhancer = new Enhancer(); public Object getProxy(Class<?> clazz){ enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } /** * 拦截所有目标类方法的调用 * 参数: * obj目标实例对象 *method 目标方法的反射对象 * args方法的参数 * proxy代理类的实例 */ public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { //代理类调用父类的方法 System.out.println("日志开始"); proxy.invokeSuper(obj, args); System.out.println("日志结束"); return null; } } //3.测试 public class Test { public static void main(String[] args) { CGLibProxy proxy = new CGLibProxy(); Train t = (Train) proxy.getProxy(Train.class); t.move(); } }</pre>

Ⅵ 如何使用Proxy模式及Java内建的动态代理机制

在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的我们的功能,我们更需要学习的是其底层是怎么样的一个原理,而AOP的原理就是java的动态代理机制,所以本篇随笔就是对java的动态机制进行一个回顾。
在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。首先我们先来看看java的API帮助文档是怎么样对这两个类进行描述的:
InvocationHandler:
InvocationHandler is the interface implemented by the invocation handler of a proxy instance.

Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler.

每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。我们来看看InvocationHandler这个接口的唯一一个方法 invoke 方法:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable

我们看到这个方法一共接受三个参数,那么这三个参数分别代表什么呢?
Object invoke(Object proxy, Method method, Object[] args) throws Throwable

proxy:指代我们所代理的那个真实对象
method:指代的是我们所要调用真实对象的某个方法的Method对象
args:指代的是调用真实对象某个方法时接受的参数

如果不是很明白,等下通过一个实例会对这几个参数进行更深的讲解。
接下来我们来看看Proxy这个类:
Proxy provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods.

Proxy这个类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler.

这个方法的作用就是得到一个动态的代理对象,其接收三个参数,我们来看看这三个参数所代表的含义:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException

loader:一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载

interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了

h:一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

好了,在介绍完这两个接口(类)以后,我们来通过一个实例来看看我们的动态代理模式是什么样的:
首先我们定义了一个Subject类型的接口,为其声明了两个方法:
public interface Subject
{
public void rent();

public void hello(String str);
}

接着,定义了一个类来实现这个接口,这个类就是我们的真实对象,RealSubject类:

public class RealSubject implements Subject
{
@Override
public void rent()
{
System.out.println("I want to rent my house");
}

@Override
public void hello(String str)
{
System.out.println("hello: " + str);
}
}

下一步,我们就要定义一个动态代理类了,前面说个,每一个动态代理类都必须要实现 InvocationHandler 这个接口,因此我们这个动态代理类也不例外:

public class DynamicProxy implements InvocationHandler
{
//这个就是我们要代理的真实对象
private Object subject;

// 构造方法,给我们要代理的真实对象赋初值
public DynamicProxy(Object subject)
{
this.subject = subject;
}

@Override
public Object invoke(Object object, Method method, Object[] args)
throws Throwable
{
//在代理真实对象前我们可以添加一些自己的操作
System.out.println("before rent house");

System.out.println("Method:" + method);

// 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
method.invoke(subject, args);

//在代理真实对象后我们也可以添加一些自己的操作
System.out.println("after rent house");

return null;
}

}

最后,来看看我们的Client类:

public class Client
{
public static void main(String[] args)
{
// 我们要代理的真实对象
Subject realSubject = new RealSubject();

// 我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的
InvocationHandler handler = new DynamicProxy(realSubject);

/*
* 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数
* 第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象
* 第二个参数realSubject.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了
* 第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
*/
Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
.getClass().getInterfaces(), handler);

System.out.println(subject.getClass().getName());
subject.rent();
subject.hello("world");
}
}

我们先来看看控制台的输出:

$Proxy0
before rent house
Method:public abstract void com.xiaoluo.dynamicproxy.Subject.rent()
I want to rent my house
after rent house
before rent house
Method:public abstract void com.xiaoluo.dynamicproxy.Subject.hello(java.lang.String)
hello: world
after rent house

我们首先来看看 $Proxy0 这东西,我们看到,这个东西是由 System.out.println(subject.getClass().getName()); 这条语句打印出来的,那么为什么我们返回的这个代理对象的类名是这样的呢?
Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
.getClass().getInterfaces(), handler);

可能我以为返回的这个代理对象会是Subject类型的对象,或者是InvocationHandler的对象,结果却不是,首先我们解释一下为什么我们这里可以将其转化为Subject类型的对象?原因就是在newProxyInstance这个方法的第二个参数上,我们给这个代理对象提供了一组什么接口,那么我这个代理对象就会实现了这组接口,这个时候我们当然可以将这个代理对象强制类型转化为这组接口中的任意一个,因为这里的接口是Subject类型,所以就可以将其转化为Subject类型了。
同时我们一定要记住,通过 Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,以$开头,proxy为中,最后一个数字表示对象的标号。
接着我们来看看这两句
subject.rent();
subject.hello("world");
这里是通过代理对象来调用实现的那种接口中的方法,这个时候程序就会跳转到由这个代理对象关联到的 handler 中的invoke方法去执行,而我们的这个 handler 对象又接受了一个 RealSubject类型的参数,表示我要代理的就是这个真实对象,所以此时就会调用 handler 中的invoke方法去执行:

public Object invoke(Object object, Method method, Object[] args)
throws Throwable
{
//在代理真实对象前我们可以添加一些自己的操作
System.out.println("before rent house");

System.out.println("Method:" + method);

// 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
method.invoke(subject, args);

//在代理真实对象后我们也可以添加一些自己的操作
System.out.println("after rent house");

return null;
}

我们看到,在真正通过代理对象来调用真实对象的方法的时候,我们可以在该方法前后添加自己的一些操作,同时我们看到我们的这个 method 对象是这样的:
public abstract void com.xiaoluo.dynamicproxy.Subject.rent()

public abstract void com.xiaoluo.dynamicproxy.Subject.hello(java.lang.String)

正好就是我们的Subject接口中的两个方法,这也就证明了当我通过代理对象来调用方法的时候,起实际就是委托由其关联到的 handler 对象的invoke方法中来调用,并不是自己来真实调用,而是通过代理的方式来调用的。
这就是我们的java动态代理机制

Ⅶ 代理模式的实现方式

下面我举个例子来说明这一切:
场景:业务类CompanyManager在调用Save方法的时候需要调用SecurityManager类判断权限是否足够
第一种实现方式,我们通常会这样做:直接在CompanyManager类中调用ISecurityManager接口的IsPass方法判断权限。
public class SimpleCompanyManager : ICompanyManager
{
可通过外部注入的属性#region 可通过外部注入的属性

public string UserName { get; set; }

public CompanyDao Dao { get; set; }

#endregion

public void Save()
{
//判断权限
ISecurityManager security = new SecurityManager();
if (security.IsPass(UserName))
{
//执行业务方法
//.
//调用DAO层方法
Dao.Save();
}
else
{
//执行其它业务方法
Console.WriteLine("您没有该权限");
}
}
}
这样CompanyManager类与ISecurityManager或SecurityManager会发生业务性耦合。聪明的朋友会发现在GOF(设计模式)中有一种模式(代理模式)可以解除这种耦合。
代理模式(Proxy Pattern):什么是代理模式?是给某一个对象提供一个代理对象,并由代理对象控制对源对象的引用。代理就是一个人或一个机构代表另一个人或者一个机构采取行动。某些情况下,客户不想或者不能够直接引用一个对象,代理对象可以在客户和目标对象直接起到中介的作用。客户端分辨不出代理主题对象与真实主题对象。代理模式可以并不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,这时候代理对象不能够创建被代理对象,被代理对象必须有系统的其他角色代为创建并传入
CompanyManager
public class CompanyManager : ICompanyManager
{
可通过外部注入的属性#region 可通过外部注入的属性

public string UserName { get; set; }

public CompanyDao Dao { get; set; }

#endregion

public void Save()
{
//执行业务方法
//.
//调用DAO层方法
Dao.Save();
}
}
CompanyProxyManager
public class CompanyProxyManager : ICompanyManager
{
public string UserName { get; set; }

private ICompanyManager target = new CompanyManager();

public void Save()
{
//判断权限
ISecurityManager security = new SecurityManager();
if (security.IsPass(UserName))
{
//调用目标对象Save方法
target.Save();
}
else
{
Console.WriteLine("您没有该权限");
}
}
}
这样,CompanyManager类就不必与判断权限的类SecurityManager耦合
代理模式作用就是接触业务耦合,保证业务的独立性
摘自 刘冬的博客园

Ⅷ 如何使用Proxy模式及Java内建的动态代理机制

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyMain {

public static void main(String[] args) {
Service service = new ServiceImpl();

Service proxy = (Service) Proxy.newProxyInstance(service.getClass().getClassLoader(),
service.getClass().getInterfaces(), new ServiceInvocationHandler(service));

System.out.println(proxy.sayHi("Arvin"));
}
}

class ServiceInvocationHandler implements InvocationHandler {

private final Service target;

public ServiceInvocationHandler(Service target) {
this.target = target;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(target, args);
}
}

interface Service {
String sayHi(String name);
}

class ServiceImpl implements Service {

@Override
public String sayHi(String name) {
return "Hi, " + name;
}
}

Ⅸ java:代理模式 是实现了InvocationHandler那个类是代理类还是$Proxy0类是代理类呢

$Proxy0是代理类,是JDK生成的。

Ⅹ java中代理模式的问题

两个new都是实例化一个对象
new ProxySubject() 是代理对象实列,但每个代理都要有一个真实的实列所以需要传递一个真实实列给它 。 及new RealSubject()

热点内容
美发店认证 发布:2021-03-16 21:43:38 浏览:443
物业纠纷原因 发布:2021-03-16 21:42:46 浏览:474
全国著名不孕不育医院 发布:2021-03-16 21:42:24 浏览:679
知名明星确诊 发布:2021-03-16 21:42:04 浏览:14
ipad大专有用吗 发布:2021-03-16 21:40:58 浏览:670
公务员协议班值得吗 发布:2021-03-16 21:40:00 浏览:21
知名书店品牌 发布:2021-03-16 21:39:09 浏览:949
q雷授权码在哪里买 发布:2021-03-16 21:38:44 浏览:852
图书天猫转让 发布:2021-03-16 21:38:26 浏览:707
宝宝水杯品牌 发布:2021-03-16 21:35:56 浏览:837