代理模式

在某些情况下,一个客户不想或者不能直接引用一个对象,此时可以通过一个称之为“代理”的第三者来实现间接引用。代理对象可以在客户端和目标对象之间起到 中介的作用,并且可以通过代理对象去掉客户不能看到 的内容和服务或者添加客户需要的额外服务。

简单来说代理模式就是通过一个代理对象去访问一个实际对象,并且可以像装饰模式一样给对象添加一些功能。

静态代理

所谓静态代理即在程序运行前代理类就已经存在,也就是说我们编写代码的时候就已经把代理类的代码写好了,而动态代理则是在程序运行时自动生成代理类。

描述起来太过抽象,看一下代码就明白是怎么回事了

接口

public interface Subject {
public void aa();
}

被代理类

public class Student implements Subject {
public void aa() {
System.out.println("添加学生");
}
}

代理类

//代理类 //与被代理类实现同一个接口
public class Proxy implements Subject {
private Student stu;
public void aa() {
if(stu==null){
stu=new Student();
}
      //在执行被代理对象的方法前做一些事情
System.out.println("============before");
      //执行被代理对象的方法
stu.aa();
      //在执行被代理对象的方法后做一些事
System.out.println("============after");
}
}

测试类

public class MyTest {
@Test
public void test1(){
Proxy proxy=new Proxy();
proxy.aa();
}
}

执行结果

============before
添加学生
============after

动态代理

观察以上代码可以发现每一个代理类只能为一个接口服务,这样一来程序开发中必然会产生过多的代理,而且,所有的代理操作除了调用的方法不一样之外,其他的操作都一样,则此时肯定是重复代码。解决这一问题最好的做法是可以通过一个代理类完成全部的代理功能,那么此时就必须使用动态代理完成。

再来看一下动态代理: 
JDK动态代理中包含一个类和一个接口:

public interface IUserDao {
public void add();
}
public class UserDaoImpl implements IUserDao {
public void add() {
System.out.println("添加学生");
}
}

测试

//JDK动态代理
@Test
public void testOne(){
final IUserDao dao=new UserDaoImpl();
InvocationHandler in=new InvocationHandler() {
/**
*
* @param proxy 代理对象
* @param method 目标对象的方法
* @param args 目标对象方法的参数
* @return
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("==========before");
Object result = method.invoke(dao, args);
System.out.println("==========after");
return result;
}
};      
      //Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
    IUserDao proxy = (IUserDao)Proxy.newProxyInstance(dao.getClass().getClassLoader(), dao.getClass().getInterfaces(),in);
proxy.add(); }

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

可以将InvocationHandler接口的子类想象成一个代理的最终操作类,

//Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)参数说明
ClassLoader loader:类加载器 
Class<?>[] interfaces:得到全部的接口 
InvocationHandler h:得到InvocationHandler接口的子类实例 

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

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

但是,JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。

Cglib动态代理 
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

public interface IUserDao {
public void add();
}
public class UserDaoImpl  {
  1. /**
  2. * 这个是没有实现接口的实现类
  3. *
  4. * @author student
  5. *
  6. */
public void add() {
System.out.println("添加学生");
}
}

测试类

 //Cglib动态代理
@Test
public void test1(){
//创建目标对象
final UserDaoImpl impl=new UserDaoImpl();
//创建一个代理对象
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(impl.getClass());
enhancer.setCallback(new MethodInterceptor() {
/**
*
* @param o 代理对象
* @param method 目标对象方法
* @param objects 目标对象方法参数
* @param methodProxy 代理类的方法
* @return
* @throws Throwable
*/
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("==============before");
Object result = method.invoke(impl, objects);
System.out.println("==============after");
return result;
}
});
UserDaoImpl proxy = (UserDaoImpl) enhancer.create();
proxy.add();
}

JAVA中代理模式的更多相关文章

  1. 【原】谈谈对Objective-C中代理模式的误解

    [原]谈谈对Objective-C中代理模式的误解 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这篇文章主要是对代理模式和委托模式进行了对比,个人认为Objective ...

  2. Java设计模式-代理模式之动态代理(附源代码分析)

    Java设计模式-代理模式之动态代理(附源代码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的差别就是:动态代理是在执行时刻动态的创建出代理类及其对象. 上篇中的静态代 ...

  3. Java学习——代理模式

    Java中的三种代理模式 一,什么是代理模式? 代理模式是一种设计模式,简单的来说就是在不改变源码的情况下,实现对目标对象的功能扩展. 比如有个歌手对象叫Singer,这个对象有一个唱歌方法叫sing ...

  4. Java中代理和装饰者模式的区别

    装饰模式:以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案: 代理模式:给一个对象提供一个代理对象,并有代理对象来控制对原有对象的引用: 装饰模式为所装饰的对象增强功能:代理模式对代理的对 ...

  5. JAVA动态代理模式(从现实生活角度理解代码原理)

    所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联. java动态代理主要是使用java.lang.reflect包中的两个 ...

  6. java之代理模式

    静态代理: java代理是一种模式--代理模式.采用代理模式,可以在不改变目标类代码的基础上,通过代理对象,来增加额外的功能(比如增加日志检测等)或者只需要目标对象的部分行为. java中,代理分为静 ...

  7. Java中代理对象的使用小结

    在某些情况下,一个客户不想或不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到了中介作用,这不仅仅使用代理模式,还可以实现适配器模式.装饰模式等. 代理对象内部含有对真实对象的引用,从而 ...

  8. java 之 代理模式(大话设计模式)

    java代理模式顾名思义,就类似于大学,我想和冰可乐,可是我又在玩游戏,于是我让我的室友帮我把可乐带回来,简单的来说我的室友就是代理,而买可乐就是需要做的行为.这是笔者理解的代理模式 大话设计模式-类 ...

  9. 【Java】代理模式、反射机制-动态代理

    关于代理模式和动态代理参考自:https://www.cnblogs.com/gonjan-blog/p/6685611.html 这里通过参考博客中的例子整理个人理解. 代理模式: 访问某个类的方法 ...

随机推荐

  1. 日常安装chocolatey报错此系统上禁止运行脚本

    查看计算机上的现用执行策略get-executionpolicy  ( 默认:Restricted ) 若要在本地计算机上运行您编写的未签名脚本和来自其他用户的签名脚本,使用以下命令将计算机上的 执行 ...

  2. syncbackse操作

    有4类操作,包括同步,备份,镜像和组 同步是前文件夹内和后文件夹内的文件同步,使得二者的所有文件保持一致,但是也可以修改不同类型文件的覆盖操作,如果左侧有文件123.txt,右侧无123.txt文件, ...

  3. Halcon 标定与准确测量

  4. 怎么样启用红米手机5的ROOT权限

    红米手机5能如何拥有了root超级权限?各位清楚,android机器有root超级权限,一旦手机拥有了root相关权限,就能够实现更强的功能,举个栗子各位公司的营销部门的妹纸,使用较多营销工具都需要在 ...

  5. python常见报错类型

     更新ing 报错类型 报错内容 错误判断 错误解决方式 IndentationError IndentationError:unexpected indent 格式错误:以外缩进   Indenta ...

  6. cobble服务器安装配置

    1.配置系统关闭 firewalld防火墙 [root@sky ~]# systemctl stop firewalld.service [root@sky ~]# systemctl disable ...

  7. load data导txt文件进mysql中的数据

    1.实验内容: 利用SQL语句“load data ”将“.txt”文本文件中的数据导入到mysql中 2.实验过程: 首先我创了一个txt(也可以是其他的),设置其编码为utf-8,在windows ...

  8. linux命令 常用

    1.linux手动连接主机ssh '主机地址' 2.编辑 vi 查看i 编辑esc 退出编辑:wq 保存退出:q 直接退出 3. linux 防火墙 centOS7 firewall-cmd --sa ...

  9. licode测试

    https://github.com/lynckia/licode/tree/master/test 使用js模拟客户端调用,也可以使用mocha来进行同样的测试

  10. 《网络是怎样连接的》PDF电子版书籍分享

    资料下载地址: 链接:https://pan.baidu.com/s/15tN9klTEsu-mQLayxI979g 提取码:ptu1 封面如下所示: