代理模式

为什么要学习代理模式? 因为这就是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. LeetCode 931. 下降路径最小和 详解

    题目详情 给定一个方形整数数组 A,我们想要得到通过 A 的下降路径的最小和. 下降路径可以从第一行中的任何元素开始,并从每一行中选择一个元素.在下一行选择的元素和当前行所选元素最多相隔一列. 示例: ...

  2. Vulnhub篇Photographerr

    0x00 靶机信息 靶机:Photographerr:1 难度:中 下载:https://www.vulnhub.com/entry/photographer-1,519/ 0x01 信息收集 靶场网 ...

  3. HTML实例-02-京东顶部导航条

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  4. JS的赋值与深浅拷贝实例

    赋值 基本类型: 传值,在栈内存中的数据发生数据变化的时候,系统会自动为新的变量分配一个新的之值在栈内存中,两个变量相互独立,互不影响的 引用类型: 传址,只改变指针的指向,指向同一个对象,两个变量相 ...

  5. Typora markdown代码块显示序号

    打开偏好设置,找到代码块 打开显示行号 然后关闭Typora重新打开 此时代码块就有行号了

  6. 前端 go.js 流程图基于vue开发项目案例

    一.流程图效果 最近一段时间在研究go.js,它是一款前端开发画流程图的一个插件,也是一个难点,要说为什么是难点,首先,它是依赖画布canvas知识开发.其次,要依赖于内部API开发需求,开发项目需求 ...

  7. iNeuOS工业互联平台,WEB组态(iNeuView)集成图报组件,满足实时数据图形化展示的需求

    目       录 1.      概述... 1 2.      平台演示... 2 3.      应用过程... 3 4.      实时数据展示效果... 5 1.   概述 市场和开源社区有 ...

  8. Codeforces Round #665 (Div. 2)A-C题解

    A. Distance and Axis 题目:http://codeforces.com/contest/1401/problem/A 题解:对于n来说分两种情况,一是奇数,二则是偶数 ①奇数:对于 ...

  9. 测试和发布说明(Alpha版本)

    Alpha版本测试报告 1.测试中发现的BUG 已修复  服务器无法发送邮件 重复上传同一首歌曲 下载进度无法实时跟进 可以多次点击上传 注册验证码失真 上传结束无法及时清理队列信息 不可重现的BUG ...

  10. 这可能是最详细的解析HTTP走私攻击的文章

    前言 HTTP Desync Attacks也就是HTTP走私攻击,是我见到的比较有趣的一种攻击方式,这里来对这种漏洞进行介绍. TL;DR HTTP走私攻击利用了HTTP协议本身的问题:HTTP中存 ...