代理模式

为什么要学习代理模式? 因为这就是SpringAOP的底层!

1. 代理模式的分类

  • 静态代理
  • 动态代理
graph LR
id1[真实的人<br/>租房的人]
id2[代理角色<br/>中介]
id3[真实角色<br/>房东]
id4[共同的目标<br/>租房]

id1 --> id2
id2 --> id3
id2 --> id4
id3 --> id4

2. 静态代理

1. 角色分析

  • 抽象角色: 一般会使用接口或者抽象类来解决
  • 真实角色: 被代理的角色
  • 代理角色; 代理真实角色, 代理真实角色后, 我们一般会做一些附属操作
  • 客户: 访问代理对象的人

2. 代码步骤

  1. 接口
package com.wang.demo01;

//租房
public interface Rent { void rent();
}
  1. 真实角色
package com.wang.demo01;

//房东
public class Host implements Rent{ @Override
public void rent() {
System.out.println("房东要出租房子!");
}
}
  1. 代理角色
package com.wang.demo01;

public class Proxy implements Rent{

    private Host host;

    public Proxy() {

    }
public Proxy(Host host) {
this.host = host;
} @Override
public void rent() {
host.rent();
seeHouse();
fee();
contract();
} //看房
public void seeHouse() {
System.out.println("中介带你看房!");
} //收中介费
public void fee() {
System.out.println("收中介费!");
} //签租赁合同
public void contract() {
System.out.println("签合同!");
}
}
  1. 客户端访问代理角色
package com.wang.demo01;

public class Client {
public static void main(String[] args) {
//房东要租房子
Host host = new Host();
//代理, 中介要帮房东租房子, 代理角色一般会有一些附属操作
Proxy proxy = new Proxy(host);
//你不用面对房东,直接面对中介租房即可
proxy.rent();
}
}

3. 代理的好处

  • 可以使真实角色的操作更加纯粹, 不用去关注一些公共的业务!
  • 公共业务交给代理模式! 实现了业务的分工!
  • 公共业务发生拓展的时候, 方便集中管理!

缺点

  • 一个真实角色就会产生一个代理角色: 代码量会翻倍 --> 开发效率会变低

4. 进一步理解

package com.wang.demo02;

public interface UserService {
void add();
void delete();
void update();
void query();
}
package com.wang.demo02;

//真实对象
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("增加了一个用户");
} @Override
public void delete() {
System.out.println("删除了一个用户");
} @Override
public void update() {
System.out.println("修改了一个用户");
} @Override
public void query() {
System.out.println("查询了一个用户");
}
}
package com.wang.demo02;

public class UserServiceProxy implements UserService{

    private UserServiceImpl userService;

    public void setUserService(UserServiceImpl userService) {
this.userService = userService;
} @Override
public void add() {
log("add");
userService.add();
} @Override
public void delete() {
log("delete");
userService.delete();
} @Override
public void update() {
log("update");
userService.update();
} @Override
public void query() {
log("query");
userService.query();
} //日志方法
public void log(String msg) {
System.out.println("[debug] " + "使用了" + msg + "方法");
}
}
package com.wang.demo02;

public class Client {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
UserServiceProxy userServiceProxy = new UserServiceProxy();
userServiceProxy.setUserService(userService);
userServiceProxy.add();
}
}

在不破坏原有代码的情况下添加新的功能!

3. 动态代理

1. 角色分析

  • 动态代理和静态代理角色一样!

  • 动态代理的代理类是动态生成的, 不是我们直接写好的!

  • 动态代理分为两大类:

    • 基于接口的动态代理: JDK的动态代理
    • 基于类的动态代理: cglib
    • java字节码实现: javassist

2. 对动态代理的两个关键类的理解

需要了解两个类: Proxy 代理, InvocationHandler 调用处理程序

Proxy ==> 生成动态代理的实例

invoke ==> 返回动态代理的结果: 包含接口的方法以及代理中添加的方法

注意:

  • 代理类不是我们定义的类,而是Proxy创建的$proxy类

  • 通过使用Proxy.newProxyInstance返回得到的动态代理的实例会被处理成\(Proxy0,\)Proxy0在调用接口方法时会调用invoke方法!

3. 动态代理的实现

package com.wang.demo04;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; //我们会用这个类, 自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler { //被代理的接口
private Object target; public void setTarget(Object target) {
this.target = target;
} //生成得到代理类
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
} //处理代理实例, 并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { log(method.getName());
//动态代理的本质, 就是使用反射机制实现
Object result = method.invoke(target, args); return result;
} public void log(String msg){
System.out.println("执行了" + msg + "方法");
} }
package com.wang.demo04;

import com.wang.demo02.UserService;
import com.wang.demo02.UserServiceImpl; public class Client {
public static void main(String[] args) { //真实角色
UserServiceImpl userService = new UserServiceImpl(); //代理角色,不存在
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//设置要代理的对象
pih.setTarget(userService);
//动态生成代理类
UserService proxy = (UserService) pih.getProxy(); proxy.add();
}
}

4. 动态代理的好处

  • 可以使真实角色的操作更加纯粹, 不用去关注一些公共的业务!
  • 公共业务交给代理模式! 实现了业务的分工!
  • 公共业务发生拓展的时候, 方便集中管理!
  • 一个动态代理中代理的是一个接口, 一般就是对应的一类业务
  • 一个动态代理类可以代理多个类, 只要是实现了同一个接口即可

Spring-代理模式的更多相关文章

  1. Spring代理模式及AOP基本术语

    一.代理模式: 静态代理.动态代理 动态代理和静态代理区别?? 解析:静态代理需要手工编写代理类,代理类引用被代理对象. 动态代理是在内存中构建的,不需要手动编写代理类 代理的目的:是为了在原有的方法 ...

  2. Spring 代理模式及AOP基本术语

    一.代理模式: 静态代理.动态代理 动态代理和静态代理区别?? 解析:静态代理需要手工编写代理类,代理类引用被代理对象. 动态代理是在内存中构建的,不需要手动编写代理类 代理的目的:是为了在原有的方法 ...

  3. Spring代理模式(jdk动态代理模式)

    有动态代理和静态代理: 静态代理就是普通的Java继承调用方法. Spring有俩种动态代理模式:jdk动态代理模式 和 CGLIB动态代理 jdk动态代理模式: 代码实现: 房东出租房子的方法(继承 ...

  4. Spring代理模式(CGLIB动态代理模式)

    jdk动态代理和CGLIB动态代理 没什么太大的区别,CGLIB动态代理不需要接口,但是需要导入jar包. 房东出租房子的方法: package com.bjsxt.proxy2; public cl ...

  5. spring代理模式 service远程调用,插件执行

    最近,研究了一下平台远程调用的过程,和service层插件执行的原理,记录一下. 1.远程service调用过程 首先看一下类的继承结构 封装调用处理过程 封装service调用接口 封装servic ...

  6. SPRING代理模式

    1.静态代理 主题对象:Student public interface Student { public String add(); } 目标对象:RealStudent public class ...

  7. Spring AOP /代理模式/事务管理/读写分离/多数据源管理

    参考文章: http://www.cnblogs.com/MOBIN/p/5597215.html http://www.cnblogs.com/fenglie/articles/4097759.ht ...

  8. 代理模式及其在spring与struts2中的体现

    代理模式 代理模式有三个角色组成: 1.抽象主题角色:声明了真实主题和代理主题的共同接口. 2.代理主题角色:内部包含对真实主题的引用,并且提供和真实主题角色相同的接口. 3.真实主题角色:定义真实的 ...

  9. Spring框架_代理模式(静态代理,动态代理,cglib代理)

    共性问题: 1. 服务器启动报错,什么原因? * jar包缺少.jar包冲突 1) 先检查项目中是否缺少jar包引用 2) 服务器: 检查jar包有没有发布到服务器下:                 ...

  10. spring设计模式_代理模式

    代理模式应该是Spring核心设计模式之一了 先说下代理模式特性: 1.有代理人和被代理人 2.对于被代理的人来说,这件事情是一定要做的,但是我又不想做,所有就找代理人来做. 3.需要获取到被代理人的 ...

随机推荐

  1. XCTF-WEB-高手进阶区-PHP2-笔记

    鬼才作者...特么卡了我那么长时间,这知识点我真不知道 o(╥﹏╥)o 拿Dirserach扫只能扫出来index.php和index.php/login 一度让我怀疑是有我不会的姿势去解这道题 最后 ...

  2. SqlServer 版本号

    RTM (no SP) SP1 SP2 SP3 SP4 SQL Server 2014      codename Hekaton  12.00.2000.8 SQL Server 2012      ...

  3. java 异常二

    一 捕获异常try…catch…finally 捕获:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理 捕获异常格式: try { //需要被检测的语句. } catch(异 ...

  4. Java程序员面试必备:Volatile全方位解析

    前言 volatile是Java程序员必备的基础,也是面试官非常喜欢问的一个话题,本文跟大家一起开启vlatile学习之旅,如果有不正确的地方,也麻烦大家指出哈,一起相互学习~ 1.volatile的 ...

  5. Wireshark中遇到的epoch time

    使用Wireshark分析DNS时遇到的Epoch time 首先看一下Wireshark分析DNS的情况(如下图): 这是协议树的第一项,第一项中的第五行出现了Epoch Time,查阅资料之后才知 ...

  6. Linux三剑客老三---grep

    1.Linux三剑客老三 过滤需要的内容,例子:grep -v oldboy hello.txt grep一般常用参数: -a:在二进制文件中,以文本文件的方式搜索数据. -c:计算找到"搜 ...

  7. Mybatis入门(一)------基本概念操作

    Mybatis简介 Mybatis是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置 ...

  8. 3分钟教会你如何发布Qt程序

    导读:Qt程序编写好以后该如何发布.本文教你使用Qt自带工具windeployqt来进行操作. 本文字数:500,阅读时长大约:3分钟 (1)编写一个简单的程序 我们先做一个简单的窗口,添加一个图片资 ...

  9. Kernel methods on spike train space for neuroscience: a tutorial

    郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! 时序点过程:http://www.tensorinfinity.com/paper_154.html Abstract 在过去的十年中,人 ...

  10. muduo源码解析2-AtomicIntegerT类

    AtomicIntegerT template<typename T> class atomicTntergerT:public noncopyable { }; 作用: 与std::ao ...