代理模式

为什么要学习代理模式? 因为这就是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. C#设计模式之14-命令模式

    命令模式(Command Pattern) 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/413 访问. 命令模式属于行 ...

  2. 怎么写简历,简历才不会被丢到非洲&#127757;

    前言 只有光头才能变强. 文本已收录至我的GitHub精选文章,欢迎Star:https://github.com/ZhongFuCheng3y/3y 最近的三歪朋友圈可以看到很多的字节.腾讯的同学都 ...

  3. s2-001漏洞复现

    struts2-001 该漏洞因为用户提交表单数据并且验证失败时,后端会将用户之前提交的参数值使用 OGNL 表达式 %{value} 进行解析,然后重新填充到对应的表单数据中.例如注册或登录页面,提 ...

  4. Centos7重置root密码(详细版)

    修改了root密码,步骤如下: 步骤一:在开机出现如下界面的时候就按“e”键     步骤二:在步骤一按下”e”键之后,出现如下界面,按 ↓键一直到底部找到“LANG=zh_CN.UTF-8”这句,在 ...

  5. utf-8变长

    utf-8变长 变长规则 一字节:0******* 两字节:110,10* 三字节:1110,10,10**** 四字节:11110**,10******,10,10* 如果是以0开头的,那么他就是一 ...

  6. Java中校验身份证号合法性(真伪),获取出生日期、年龄、性别、籍贯

    开发过程中有用的身份证号的业务场景,那么校验身份证的合法性就很重要了,另外还有通过身份证获取出生日期.年龄.性别.籍贯等信息, 下面是本人在开发中用到的关于校验身份证真伪的工具类,可以直接拿来使用,非 ...

  7. mysql索引类型:FULLTEXT、NORMAL、SPATIAL、UNIQUE的区别

    1. Normal 普通索引 2. Unique 唯一索引 3. Full Text 全文索引 4. SPATIAL 空间索引 5. btree索引和hash索引的区别 6. 在实际操作过程中,应该选 ...

  8. 结对项目:四则运算题目生成器(Java)

    目录 一.需求分析 二.开发计划 三.实现方案 3.1 项目结构 3.2 代码说明 3.2.1 出题功能代码 3.2.3 批卷功能代码 3.2.3 四则运算功能代码 四.效能分析 4.1 程序效能 4 ...

  9. Django中views数据查询使用locals()函数进行优化

    优化场景 利用视图函数(views)查询数据之后可以通过上下文context.字典.列表等方式将数据传递给HTML模板,由template引擎接收数据并完成解析.但是通过context传递数据可能就存 ...

  10. ID3\C4.5\CART

    目录 树模型原理 ID3 C4.5 CART 分类树 回归树 树创建 ID3.C4.5 多叉树 CART分类树(二叉) CART回归树 ID3 C4.5 CART 特征选择 信息增益 信息增益比 基尼 ...