`

Java之代理(一)

 
阅读更多

 一.概念

代理是什么呢?举个例子,一个公司是卖摄像头的,但公司不直接跟用户打交道,而是通过代理商跟用户打交道。如果:公司接口中有一个卖产品的方法,那 么公司需要实现这个方法,而代理商也必须实现这个方法。如果公司卖多少钱,代理商也卖多少钱,那么代理商就赚不了钱。所以代理商在调用公司的卖方法后,加上自己的利润然后再把产品卖给客户。而客户部直接跟公司打交道,或者客户根本不知道公司的存在,然而客户最终却买到了产品。

 

专业点说:代理模式是对象的结构型模式,代码模式给某一个对象提供代理,并由代理对象控制原对象(目标对象,被代理对象)的引用。简单点说,就是通过一个工厂生成一个类的代理对象,当客户端使用的时候不直接使用目标对象,而是直接使用代理对象。摘抄于网络

二、代理模式

代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,如图1所示。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。

图1:Proxy模式

三、代理分类

按照代理类的创建时期,代理类可分为两种。

  • 静态代理类:由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
  • 动态代理类:在程序运行时,运用反射机制动态创建而成。   

动态代理目前有两种代理机制:一种是基于JDK的动态代理;另一种是基于CGLib的动态代理。

JDK本身只提供接口的代理,而不支持类的代理。

CGLib本身只支持类的代理,而不支持接口的代理。   

     JDK静态代理

     JDK动态代理

     CGLIB动态代理

 

静态代理代码示例

 

首先创建接口:

Java代码  收藏代码
  1. package org.iti.wxl.staticproxy;  
  2. /** 
  3.  * 接口 
  4.  */  
  5. public interface UserService {  
  6.              public void saveUser();  
  7.              public void deleteUser();  
  8. }  

对接口的实现:(这里就不连接数据库了,只做简单的实例)

 

Java代码  收藏代码
  1. package org.iti.wxl.staticproxy;  
  2.   
  3. public class UserServiceImpl implements UserService {  
  4.     @Override  
  5.     public void saveUser() {  
  6.         System.out.println("==user saved!==");  
  7.     }  
  8.     @Override  
  9.     public void deleteUser() {  
  10.         System.out.println("==user deleted!==");  
  11.     }  
  12. }  

代理类:

Java代码  收藏代码
  1. package org.iti.wxl.staticproxy;  
  2.   
  3. public class UserServiceImplProxy implements UserService {  
  4.       
  5.     private UserServiceImpl userServiceImpl;  
  6.     public UserServiceImplProxy(UserServiceImpl userServiceImpl) {  
  7.         this.userServiceImpl = userServiceImpl;  
  8.     }  
  9.   
  10.     @Override  
  11.     public void saveUser() {  
  12.         System.out.println("save begin!");  
  13.         userServiceImpl.saveUser();  
  14.         System.out.println("save end!");  
  15.     }  
  16.       
  17.     @Override  
  18.     public void deleteUser() {  
  19.         System.out.println("delete begin!");  
  20.         userServiceImpl.deleteUser();  
  21.         System.out.println("delete end!");  
  22.     }  
  23. }  

      代理类同样实现了UserService接口,代理类持有UserServiceImpl,并且重写了UserService接口里的方法,在方法里添加了逻辑。

 

测试方法:

Java代码  收藏代码
  1. package org.iti.wxl.staticproxy;  
  2.   
  3. public class StaticProxy {  
  4.     //静态代理方法测试  
  5.     public static void main(String[] args) {  
  6.         UserServiceImpl userServiceImpl = new UserServiceImpl();  
  7.         UserServiceImplProxy userServiceImplProxy =   
  8.                 new UserServiceImplProxy(userServiceImpl);  
  9.         userServiceImplProxy.saveUser();  
  10.         System.out.println("=============");  
  11.         userServiceImplProxy.deleteUser();  
  12.     }  
  13. }  

把创建的UserServiceImpl交给代理类UserServiceImplProxy,由它的实例执行数据逻辑操作。

 

方法运行结果如下:

Java代码  收藏代码
  1. save begin!  
  2. ==user saved!==  
  3. save end!  
  4. =============  
  5. delete begin!  
  6. ==user deleted!==  
  7. delete end! 

  代理类中添加的逻辑在方法运行时被执行了。 

    观察代码可以发现每一个代理类只能为一个接口服务,这样一来程序开发中必然会产生过多的代理,而且,所有的代理操作除了调用的方法不一样之外,其他的操作都一样,则此时肯定是重复代码。

 

    解决这一问题最好的做法是可以通过一个代理类完成全部的代理功能,那么此时就必须使用动态代理完成。

 

 jdk动态代理

 

    jdk动态代理中包含一个类和一个接口,用到了java的反射机制:

Java代码  收藏代码
  1. public interface InvocationHandler {   
  2. public Object invoke(Object proxy,Method method,Object[] args);  
  3. }  

  参数说明:
      Object proxy:代理类对象。   
      Method method:要调用的方法  
      Object[] args:方法调用时所需要的参数

 

    下面用代码说明jdk动态代理的使用

接口类:

Java代码  收藏代码
  1. package org.iti.wxl.dynamicproxy;  
  2.   
  3. public interface UserService {  
  4.     public void addUser();  
  5.     public void deleteUSer();  
  6. }  

对接口的实现:

Java代码  收藏代码
  1. package org.iti.wxl.dynamicproxy;  
  2.   
  3. public class UserServiceImpl implements UserService {  
  4.     @Override  
  5.     public void addUser() {  
  6.         System.out.println("==add user==");  
  7.     }  
  8.     @Override  
  9.     public void deleteUSer() {  
  10.         System.out.println("==delete user==");  
  11.     }  
  12. }  

代理类:

Java代码  收藏代码
  1. package org.iti.wxl.dynamicproxy;  
  2.   
  3. import java.lang.reflect.InvocationHandler;  
  4. import java.lang.reflect.Method;  
  5. import java.lang.reflect.Proxy;  
  6. public class UserServiceImplProxy implements InvocationHandler {  
  7.     private Object target;  
  8.       
  9.     public Object bind(Object target){  
  10.         this.target = target;  
  11.         return Proxy.newProxyInstance(target.getClass().getClassLoader(),   
  12.                 target.getClass().getInterfaces(), this);  
  13.     }  
  14.     @Override  
  15.     public Object invoke(Object proxy, Method method, Object[] args)   
  16.             throws Throwable {  
  17.         Object result = null;  
  18.         System.out.println("user add begin!");  
  19.         result = method.invoke(target, args);  
  20.         System.out.println("user add end!");  
  21.         return result;  
  22.     }  
  23. }  

 代理类主要负责两项功能:1、把Object转化成代理类的一个实现;2、为方法添加逻辑(如日志,性能测试等)。

 

测试类:

Java代码  收藏代码
  1. package org.iti.wxl.dynamicproxy;  
  2.   
  3. public class DynamicProxy {  
  4.     public static void main(String[] args) {  
  5.         UserServiceImplProxy proxy = new UserServiceImplProxy();  
  6.         UserService userServiceProxy = (UserService)proxy.  
  7.                 bind(new UserServiceImpl());  
  8.         userServiceProxy.addUser();  
  9.         System.out.println("========");  
  10.         userServiceProxy.deleteUSer();  
  11.     }  
  12. }  

 

 测试结果:

Java代码  收藏代码
  1. user add begin!  
  2. ==add user==  
  3. user add end!  
  4. ========  
  5. user add begin!  
  6. ==delete user==  
  7. user add end!  

分析:

可以将InvocationHandler接口的子类想象成一个代理的最终操作类。 
Proxy 类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了操作方 法: newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 
参数说明: 
  ClassLoader loader:类加载器
  Class<?>[] interfaces:全部的接口
  InvocationHandler h:InvocationHandler接口的子类实例

 

在Proxy类中的newProxyInstance()方法中需要一个ClassLoader类的实例,ClassLoader实际上对应的是类加载器,在Java中主要有一下三种类加载器:
Booststrap ClassLoader:此加载器采用C++编写,一般开发中是看不到的。
Extendsion ClassLoader:用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类。
AppClassLoader:(默认)加载classpath指定的类,是最常使用的是一种加载器。

 

这三个类的继承关系是Extendsion ClassLoader继承Booststrap ClassLoader,AppClassLoader继承Booststrap ClassLoader,每加载一个类都现有父类加载,父类没有再用其孩子类加载,保证了安全性。另外我们也可以写自己的类加载器,为类加载器加密等。

 

动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编 写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。

 

 

 

分享到:
评论

相关推荐

    Java代理模式Java动态代理

    ### Java代理模式与Java动态代理详解 #### 一、代理模式概述 代理模式是一种软件设计模式,它在客户端和目标对象之间提供了一种间接层。这种模式的主要目的是控制客户端对目标对象的访问,并且可以在不修改原有...

    java操作IE代理

    将它放在"jdk/bin"目录下,是因为这是Java默认寻找本地库的路径之一,使得Java程序能够找到并加载这个库。 实现Java操作IE代理的基本步骤如下: 1. **加载本地库**:使用`System.loadLibrary()`方法加载"ICE_...

    java动态代理demo

    Java动态代理是Java编程中一个重要的特性,它允许我们在运行时创建代理对象,这些代理对象可以代表并增强原对象的功能。动态代理在很多场景下都非常有用,比如日志记录、性能监控、事务管理等。本示例将带你深入理解...

    JAVA静态代理和动态代理

    在Java编程语言中,代理模式是一种设计模式,它允许我们为一个对象提供一个代理以控制对这个对象的访问。代理模式通常用于增加额外的功能或在访问原对象时进行额外的操作,比如日志记录、安全控制、性能度量等。Java...

    java动态代理实例

    Java动态代理是Java语言提供的一种在运行时创建代理对象的技术,它允许我们为已存在的接口创建代理类,以便在调用真实目标对象的方法时添加额外的功能或行为。在这个实例中,我们将深入探讨Java动态代理的核心概念,...

    java实现免费代理IP的获取方式 并实时校验代理IP是否有效

    Java 实现免费代理IP的获取方式 并动态实时校验是否有效,java文件项目内含有Jsoup的Jar包(Jsoup是加工过的,含请求),有2个主入口程序: 其一:用于请求代理IP,并立即校验是否是一个有效的代理IP,如果有效,...

    java之代理.pdf

    Java代理主要分为静态代理和动态代理。静态代理需要目标对象和代理对象都实现相同的接口,代理对象在编译时就已经确定,适用于简单场景。动态代理则更灵活,代理类和代理对象在运行时动态生成,不需要预先定义接口,...

    Java 静态代理模式

    Java静态代理模式是一种设计模式,它允许我们为一个对象提供一个代理,以便增强或扩展其功能,同时不改变原有对象的代码。在Java中,静态代理是通过在代理类中显式实现目标接口来实现的。下面将详细介绍静态代理模式...

    Java静态代理与动态代理demo

    在Java编程中,代理模式是一种常用的结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。代理模式通常用于增加额外的功能或在访问原始对象时进行额外的操作,比如日志记录、性能监控等。Java提供了两...

    一个简单的java动态代理的实例

    Java动态代理是Java提供的一种在运行时创建代理对象的技术,主要由`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口组成。在这个简单的Java动态代理实例中,我们将探讨如何利用这两个核心...

    Java写http代理服务器

    通过以上步骤,你可以构建一个基本的Java HTTP代理服务器。当然,实际的项目可能会涉及更多细节,如支持HTTPS、代理链、重定向处理、代理认证等。提供的压缩包文件可能包含有关此主题的教程、代码示例和相关资源,...

    java动态代理机制

    Java动态代理机制是Java语言提供的一种强大的功能,它允许在运行时创建代理对象来实现特定接口,从而可以灵活地扩展或增强已有代码的功能。在Java中,动态代理主要通过两个类来实现:`java.lang.reflect.Proxy` 和 `...

    java动态代理 经典文章(word 2007格式的)

    Java动态代理是Java编程中一个重要的特性,它允许在运行时创建代理对象,这些代理对象可以代表并增强原对象的功能。动态代理主要应用于面向切面编程(AOP)和事件监听等场景,使得代码更加模块化,易于维护。以下是...

    JAVA设计模式之代理模式实例

    在Java编程领域,设计模式是一种解决常见问题的模板或最佳实践,它被广泛应用于软件开发中以提高代码的可读性、可维护性和可扩展性。代理模式是设计模式的一种,它提供了一种对目标对象进行增强或者控制访问的方式。...

    java动态代理类的实例

    Java动态代理是Java语言提供的一种高级特性,它允许我们在运行时创建一个代理对象来代替某个接口或类的对象,这个代理对象能够对方法调用进行拦截和处理。在Java中,动态代理主要通过`java.lang.reflect.Proxy`类和`...

    Java 动态代理和Cglib代理(二)

    然而,Java动态代理有一个局限性,即它只能代理实现了接口的对象,无法代理没有接口的类。为了解决这个问题,Cglib应运而生。 Cglib(Code Generation Library)是一个强大的代码生成库,它可以在运行时动态地生成...

    Java 动态代理详解(学习资料)

    如果接口有多个方法,代理类也需要一一实现,当接口方法增加时,代理类也要随之修改。2. 代理类和目标类强耦合。代理类需要直接引用目标类,这限制了代码的可扩展性和复用性。JDK 动态代理JDK 提供了 java.lang....

    Java动态代理两种实现方式

    Java动态代理技术是Java编程中一个非常重要的特性,它允许我们在运行时动态创建具有特定行为的对象。这种技术常用于AOP(面向切面编程)和框架中,如Spring AOP,用于实现方法拦截、事务管理等功能。Java提供了两种...

    用Java实现的代理模式之动态代理

    `代理模式之动态代理.exe`可能是一个视频播放程序,其中详细讲解了如何实现和理解动态代理。`代理模式之动态代理.ppt`则可能是一个PPT文档,提供了代理模式的理论介绍和代码示例。 4. **学习与实践** 要深入理解...

Global site tag (gtag.js) - Google Analytics