-
ssm-spring代理模式(静、动态)
一、代理模式
- 代理模式的定义: 为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
- 组成: 抽象角色:通过接口或抽象类声明真实角色实现的业务方法。
- 分类: 代理模式分为静态代理、动态代理。
代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
静态代理:由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了 动态代理:在实现阶段不用关心代理类,而在运行阶段才指定哪一个对象。
二、静态代理
假定现在有接口ISpeak
,学校(School
)和校长(Principal
)都实现了该接口,由于种种原因,学校不能发言 而是由校长代表学校进行发言,这个场景中,目标角色为学校,代理角色为校长:发言接口:
public interface ISpeak {
/**
* 发言
*/
void speak();
}
学校实现了发言接口:
public class School implements ISpeak{
@Override
public void speak() {
System.out.println("开学了");
}
}
校长实现了发言接口:
public class Principal implements ISpeak {
private School school;
/**
* 将目标角色注入到代理角色,使代理角色持有目标角色,可以用setter或者构造器注入
* @param school
*/
public Principal(School school) {
this.school = school;
}
@Override
public void speak() {
System.out.println("校长代理学校发言:");
if (school != null) {
school.speak();
}
}
}
编写测试进行验证:
public class ProxyTest {
@Test
public void test() {
ISpeak speak = new Principal(new School());
speak.speak();
}
}
结果如下:三、动态代理
和静态代理不同,动态代理不会在实现阶段去关心代理类,而是在运行阶段通过反射实现,接着上个例子分析动态代理。动态代理类:
public class DynamicProxy implements InvocationHandler {
/**
* 被代理的真正对象
*/
private Object obj;
public DynamicProxy(Object obj) {
this.obj = obj;
}
public Object proxy() {
//返回一个实现了目标对象所有接口的实例对象(代理对象),该对象由jvm运行时组装
return Proxy.newProxyInstance(getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
}
/**
* 代理对象每次执行接口方法时,都会调用本方法,本方法中将通过反射来实现真正对象的方法调用
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理通过反射执行方法开始[1]:" + method);
Object invoke = method.invoke(obj, args);
System.out.println("代理通过反射执行方法结束[2]:" + method);
return invoke;
}
}
具体体现在,静态代理是用校长类,在代码实现阶段对学校进行代理。动态代理则是使用java.lang.reflect.Proxy
,在运行阶段jvm通过反射返回一个实现了发言接口的动态代理对象。 配合java.lang.reflect.InvocationHandler
接口,代理对象每次执行发言接口时都会调用该接口的invoke方法,此时我们再在该invoke方法中用调用真正对象的发言方法, 实现动态代理。(这里举例的发言接口可以替换为任何接口)编写测试方法:
@Test
public void test() {
ISpeak speak = (ISpeak) new DynamicProxy(new School()).proxy();
System.out.println("测试:test[1]");
speak.speak();
System.out.println("测试:test[2]");
}
四、总结
代理模式是spring aop思想的基础,特别是动态代理,例如:aop再不破坏原有业务代码逻辑的同时,植入日志系统就是动态代理一个常用场景。
出处:https://www.cnblogs.com/zhoux123/p/15219209.html
最新更新
python爬虫及其可视化
使用python爬取豆瓣电影短评评论内容
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
uniapp/H5 获取手机桌面壁纸 (静态壁纸)
[前端] DNS解析与优化
为什么在js中需要添加addEventListener()?
JS模块化系统
js通过Object.defineProperty() 定义和控制对象
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比