一、什么是代理

  代理是一种设计模式,它提供了一种通过代理访问目标对象的方式。在应用代理之前,我们调用对象的过程如下:

  客户端直接调用对象并获取返回值。而应用了代理之后,我们调用对象的过程变成如下:

  客户端先调用代理,代理再去调用目标对象,目标对象执行后的返回值先经过代理,再由代理返回给客户端。

二、代理的作用

  应用代理后,任何对目标对象的调用和目标对象的返回值都要经过代理,因此我们可以在代理中实现非侵入式的代码扩展,让我们在不用修改源码的情况下对目标对象的某个方法的功能进行增强。我们可以在调用目标对象方法的前后进行任何操作,甚至阻止对目标对象方法的调用。

  除此之外,代理还是AOP编程思想的一种实现方式。

三、代理的实现

  在本例中,我们将通过静态代理和动态代理,实现在目标对象的方法执行前添加“权限检查”功能和方法执行后添加“日志记录”功能。

  静态代理和动态代理都要求被代理的目标对象有实现接口,且要增强的方法在接口中必须有定义,因此这里我们创建一个Test1接口和它的实现类Test1Impl,该类实例化的对象就是接下来将要被代理的目标对象。

 public interface Test1 {

     public void service1();

 }
 public class Test1Impl implements Test1{

     @Override
public void service1() {
System.out.println("业务处理……");
} }

  另外,我们还需要创建一个切面类Aspect,里面包含我们要添加的功能的代码。

 public class Aspect {

     public static void check() {
System.out.println("权限检查……");
} public static void log() {
System.out.println("日志记录……");
}
}

1、静态代理的实现

  静态代理的实现比较简单,我们只需编写一个代理类Test1Proxy:

 public class Test1Proxy implements Test1{    //代理类需要实现与目标对象相同的接口

     private Test1 test1 = null;

     public Test1Proxy(Test1 test1) {       //获取目标对象
this.test1 = test1;
} @Override
public void service1() {           //代理对象的方法
Aspect.check();              //权限检查
test1.service1();             //代理对象调用目标对象方法
Aspect.log();               //日志记录
} }

  客户端代码如下:

 public class Main {
public static void main(String[] args) {
Test1 test1 = new Test1Impl();     //创建目标对象
test1 = new Test1Proxy(test1);     //创建目标对象的代理对象
test1.service1();             //代理对象调用service1()方法
}
}

  运行结果如下:

  静态代理虽然实现简单,但存在一些问题。

  第一,如果我们要对实现了不同接口的多个对象实现代理,就要编写实现了不同接口的代理类。

  第二,如果要对目标对象的多个方法进行增强,则需要在多个方法中重复编写新功能的代码。

  第三,一旦接口需要添加方法,我们不仅需要修改目标类,还需要额外修改代理类。

  要解决这些问题,就需要用到动态代理。

2、动态代理的实现

  同静态代理一样,动态代理也需要编写一个代理类,但不同的是,我们需要编写的是可以动态产生代理对象的代理工厂类ProxyFactory,代码如下:

 import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class ProxyFactory { public static Object getProxyObject(Object targetObject) {   //根据目标对象得到代理对象
return Proxy.newProxyInstance(                 //返回创建的代理对象
targetObject.getClass().getClassLoader(),       //获取目标对象的类加载器
targetObject.getClass().getInterfaces(),        //获取目标对象实现的接口
new InvocationHandler() {                 //匿名内部类,含有代理对象的方法
/**
* 调用目标对象的方法时,都会先调用此方法
* proxy:代理对象
* method:调用目标对象方法名
* args:调用目标对象方法时的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Aspect.check();                       //权限验证
Object result = method.invoke(targetObject, args);  //通过反射调用目标对象方法
Aspect.log();                        //日志记录
return result;                       //返回目标对象方法执行后的返回值
}
});
}
}

  编写好代理工厂类后,我们就可以来产生代理对象,客户端代码如下:

 public class Main {
public static void main(String[] args) {
Test1 test1 = new Test1Impl();               //创建目标对象
test1 = (Test1) ProxyFactory.getProxyObject(test1);   //根据目标对象创建代理对象
test1.service1();                      //通过代理对象调用目标对象的方法
}
}

  运行结果如下:

  与静态代理相比,动态代理会自动的根据目标对象创建对应的代理对象,并且在执行过程中动态的对目标对象的方法进行增强,这就降低了代码编写量和维护成本。但动态代理会对接口中所有定义过的方法进行增强,如果希望只对部分方法进行增强,需要在invoke()方法中增加判断逻辑。

Java静态代理与动态代理实现的更多相关文章

  1. 【Java】代处理?代理模式 - 静态代理,动态代理

    >不用代理 有时候,我希望在一些方法前后都打印一些日志,于是有了如下代码. 这是一个处理float类型加法的方法,我想在调用它前打印一下参数,调用后打印下计算结果.(至于为什么不直接用+号运算, ...

  2. Java:静态代理 and 动态代理

    代理模式是常用的设计模式,其特征是代理类与委托类具有相同的接口,在具体实现上,有静态代理和动态代理之分.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并 ...

  3. Java基础-静态代理与动态代理比较

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

  4. java中静态代理,动态代理知识的补充

    文章转载自:http://blog.csdn.net/jialinqiang/article/details/8950989 一.Java动态代理 相对于静态代理的代理类在编译时生成(.class文件 ...

  5. java静态代理与动态代理简单分析

    原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/5860749.html 1.动态代理(Dynamic Proxy) 代理分为静态代理和动态代理 ...

  6. 黑马程序员:Java基础总结----静态代理模式&动态代理

    黑马程序员:Java基础总结 静态代理模式&动态代理   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 静态代理模式 public  class  Ts {   ...

  7. Java静态代理和动态代理

    今天介绍一下代理设计模式,在业务场景中使用代理模式的好处有很多,包括什么权限校验,事务管理等等,具体有什么好处大家自动百度吧,我这里只解释代理模式的设计原理.首先这个设计模式出来的时候先是静态代理模式 ...

  8. java中的静态代理和动态代理,入门整理

    静态代理和动态代理主要解决的问题是:在直接访问对象时带来的问题,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后 ...

  9. Java 静态代理与动态代理

    代理模式 设想你的项目依赖第三方,但是你需要对其接口做一些数据检验.性能数据记录.异常处理等,合适的方法就是使用设计模式里的代理模式. 代理模式是常用的java设计模式,代理类与委托类有同样的接口,代 ...

  10. java之静态代理和动态代理

    我们以几个问题,来开始我们今天的学习,如果下面几个问题,你都能说出个一二,那么恭喜你,你已经掌握了这方面的知识.1,什么是代理模式?2,Java中,静态代理与动态代理的区别?3,Spring使用的是J ...

随机推荐

  1. Java集合总结(三):堆与优先级队列

    堆 满二叉树:满二叉树是指,除了最后一层外,每个节点都有两个孩子,而最后一层都是叶子节点,都没有孩子. 完全二叉树:完全二叉树不要求最后一层是满的,但如果不满,则要求所有节点必须集中在最左边,从左到右 ...

  2. vs2015 调试 无法启动程序

    应用程序输出在这个目录 E:\learn\3dlesson\lesson1_createwindow\build\Debug 项目属性 解决方案: 把项目设为启动项目.

  3. windows中命令行窗口提权到管理员权限.windows 的 sudo

    命令行环境中获取管理员权限 第一种方法 (最爽,但是被运行的命令会被当成新进程运行,运行完成后就自动关闭了.) 把以下代码复制到记事本中保存为sudo.vbs 然后移动到PATH任意目录中,如wind ...

  4. ImportError: No module named rospy

    Traceback (most recent call last): File "manage.py", line 4, in <module> import rosp ...

  5. jenkins安装NodeJS遇到的问题

    1.通过插件管理安装插件失败 可以修改地址或者手动上传 下载插件失败查看:https://www.cnblogs.com/SmilingEye/p/11424235.html 2.不显示NodeJS配 ...

  6. elasticsearch _bulk api

    https://www.elastic.co/guide/cn/elasticsearch/guide/current/bulk.htmlbulk API 允许在单个步骤中进行多次 create . ...

  7. csp-s模拟95

    近两场开始文件评测,感觉和平时真不太一样. 考试时间是多了$10min$,但处理文件.输入输出什么的杂事也是忙来忙去.这可能也最像真实的$csps$了,稍有疏忽可能都是致命伤. T1.T2挂的对拍全打 ...

  8. php-fpm(绕过open_basedir,结合ssrf)

    环境的安装->https://www.cnblogs.com/zaqzzz/p/11870489.html 1.nginx的畸形访问 因为安装的是php7.0,所以需要手动修改一下(版本低的时候 ...

  9. 冲刺阶段——Day2

    [今日进展] 完成黄金点游戏的算法与代码架构. 使用文字界面完成任务 码云链接:https://gitee.com/jxxydwt1999/20175215-java/blob/master/Gold ...

  10. Oracle中shrink space命令

    shrink_clause:   http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_3001.htm#i2192484 ...