文档章节

代理模式

o
 onedotdot
发布于 2017/08/09 17:05
字数 2416
阅读 10
收藏 0
点赞 0
评论 0

 

1、代理模式简单示意图

 

作用:增强某个对象的某个或部分功能

缺点:

由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

 

代理模式分为静态代理和动态代理

2、静态代理又称为装饰设计模式;

核心实现思路如同  装饰设计模式  

代理对象继承要增强的类或者接口;然后在代理对象里面传入要增强(代理)的对象,以及增强的功能对象;

 

静态代理的缺点就是:

(1)、如果需要代理多个对象,就要写多个代理对象类;会写成千上百个代理对象;

(2)、代理对象类代码因为继承导致耦合性太强;

解决这类问题,最好的方法就是动态代理了;动态代理对代理类是透明了,不需要参与,会动态生成,而对于目标接口只需要传入接口就可以了;

3、动态代理分两种情况

动态代理内部原理图;

log,通常是一个新的功能增强对象;而不是一行代码;

 

 

1)jdk代理

对于有接口的对象,一般可以使用jdk动态代理;

	Advice advice = null;
	Object target = null;
	public Advice getAdvice() {
		return advice;
	}
	public void setAdvice(Advice advice) {
		this.advice = advice;
	}
	public Object getTarget() {
		return target;
	}
	public void setTarget(Object target) {
		this.target = target;
	}


public Object getProxy(){ // 这里如果需要通过传参给内部类的话,就需要加个final修饰符
		Object proxy = Proxy.newProxyInstance(
				target.getClass().getClassLoader(),
				target.getClass().getInterfaces(),
				new InvocationHandler(){
				
					public Object invoke(Object proxy, Method method, Object[] args)
							throws Throwable {


						advice.beforeMethod(method);
						Object retVal = method.invoke(target, args);
						advice.afterMethod(method);
						return retVal;						
						
					}
				}
				);
		return proxy;
	}

 

jdk动态代理的优点:

                动态的产生代理对象,只需要一个拦截器就够了;把增强功能的对象和目标对象传入构造函数即可;可以自定义一个myIntercept去继承那个拦截器对象,然后在构造器里面去传入目标对象和功能增强对象;

核心机制:通知对象+目标对象传入后在调用处理器InvocationHandler中传入后在invoke方法里面进行直接整合;目标对象的方法已经被透明了,但是通知对象方法还得程序员自己去写;

缺点:

            如果在jdk proxy里面做事务的判断,因为要对不同的方法分别做事务判断,将会是一件非常复杂的事情;一般只能通过if(Method.Name=="save")这样的方式去判断要不要开启事务,所以如果dao层有很多的话,就会会特别的麻烦;因为每一个方法都要去判断;

            拦截器的方法还需要程序员去修改,没法做到彻底的松耦合;

2)、CGLib库


这是对于没有接口实现的一些类,CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库。


CGLib实现的是MethodInterceptor(方法拦截器),而JDKProxy实现的是InvocationHandler(方法调用处理器),

public class MyInterceptor implements MethodInterceptor{
	private Object target;
	private Transaction transaction;
	public MyInterceptor(Object target,Transaction transaction){
		this.target = target;
		this.transaction = transaction;
	}
	


	public Object createProxy(){
		Enhancer enhancer = new Enhancer(); //CGLIb产生代理对象的加强器,这个类命名特别恰到好处
		enhancer.setCallback(this);//this代表拦截器对象
		enhancer.setSuperclass(target.getClass());//设置代理类的父类为目标类
		return enhancer.create();
	}
	/**
	 * 该方法的内容和JdkProxy中的invoke方法的内容是一样的
	 */
	public Object intercept(Object arg0, Method method,  Object[] args,
			MethodProxy arg3) throws Throwable { 
		this.transaction.beginTransaction();
		method.invoke(this.target, args);
		this.transaction.commit();
		return null;
	}
	
}

参考  java静态代理和动态代理   http://layznet.iteye.com/blog/1182924

 

4、代理模式应用

Spring的AOP  即面向切面编程;

重要概念:切面,通知,切入点,连接点,目标对象,织入

一般的,需要增强的功能通常叫做通知;切面是通知对象,通知是功能方法;

代理对象的方法,就是目标+通知方法,就是拦截器中的invoke方法;

但是实际开发中通知和目标方法是完全松耦合的;

 

其实和工厂模式的代理特性来说,工厂模式是真正的做代理,而AOP实质实在做切面;

但是通常说代理模式,一般都是做功能增强的意思;否则就只是如同工厂模式,做一个解耦的作用了;

功能并没有进行增强;所以说工厂模式是虚构造器;

 

AOP基本常用应用的场景

    前置通知,后置通知,异常通知,最终通知,环绕通知;

一般Aop应用场景是在  很多模块都需要使用的某个功能,经常用的,但是与具体业务场景有没有多大关系的功能,才把这个公用的东西抽取出来形成切面;比如日志,权限等等;比如spring的声明式事务处理;

 

5、由功能增强联想延伸

根据oop的思想,因为目的是为了更好的扩展和维护包括可读性,oop明显是优于po的方式就是更易于扩展,重用性,和灵活性,而且便于维护,所以这个取决于oop的封装特性;

于是有了这个封装特性之后自然就限制了一个对象的功能了;因为不能太囊肿了,否则那和面向过程就没有什么区别了;

于是问题就来了;

1)怎么做到功能增强呢?

继承,构造函数和引用注入

oop自然就多了一个很强大的特性,就是继承了;这就是静态代理了;

同时其实也隐含了两个很重要的特性,就是  引用,通过set方式注入,或者通过构造器初始化注入;

这就是oop自带的功能增强的特性;

oop也同时自带一个很重要的特性,就是颗粒度;就是耦合性理论上可以趋于零;

于是,慢慢的就有了代理,spring发展成了aop,后来发展了soa,包括调度jndi都是类似道理,再后来的微服务;

2)是否存在功能减弱呢?

话说有功能增强,肯定也得有功能减弱或者功能屏蔽了;

很简单的道理,比如给合作伙伴系统进行沟通,需要提供交互协议和接口;

还比如,如果需要去争夺商业市场,需要给市场一个接口给市场这个产品的定位,让各种配套商品以这个作为标准服务来开发配套设施;

一方面你要和别人合作,不能把所有细节都给别人,另一方面,你要给市场顶一个标准优先抢夺市场,你的给别人一个可用的方案,但是同时又不能把细节透漏给竞争对手;更重要的是自己的实现细节对别人是透明的,这样自己就可以很自由的瞎折腾了;

其实接口就是一个标准而已,提供对外的公共扩展的一个标准,告诉别人我是这么来读取的,你们按照我的来;我就会认识;

所以这里就需要一个功能减弱的功能;所以oop也自带一个功能就是多态了;

接口和抽象函数基本可以这么去理解;

抽象函数有一个典型的应用场景就是  模板方法设计模式了; 也就是减弱部分功能的实现而已;

 

其实人际关系种也是如此道理,都是用接口去交接的;

不可能用具体的实现类去交接,因为这样会很容易被鄙视,进而别人对你不尊敬等等之类的阻碍工作进行的事情;

但是实际中一般情况都还是用实现类去交接,这样一方面显得很真诚,另一方面其实还是接口交接的效果;因为你比别人高很多维度,你给他讲实现类的原理,对方也听不懂,然后最后只知道你很牛叉,然后就完了,至于实现类,就算别人把代码拿过去,也只是不明觉厉而已;

就是高维对低维,永远只是接口,不可能是实现类;因为看不懂;

其实那种实现类之间的鄙视,也只有低段位的人才会,一般高段位不是鄙视,而是惺惺相惜的感觉,就如同诸葛亮和司马懿,所以只要把自己的段位提高,就自然不会出现那种比较恶心的局面了;

 

================

 

其实发现软件实现就那些场景,把那些场景都搞透彻了,然后就彻底的透彻了;

根本就没有什么难度的问题了;做人做事好像都是这样;

其实就和人的分析一样,其实就那么几个需求,都是有限的需求,而一个系统的场景其实也是有限的;

只要知道了和搞透彻了那些场景,然后把里面的问题也都搞明白了,场景+事务+问题的思考模式搞明白之后,自然就都通了,

阿里,通过自动化让16年的双十一员工正常下班了;

 

© 著作权归作者所有

共有 人打赏支持
o
粉丝 6
博文 321
码字总数 14350
作品 0
朝阳

暂无文章

Spring基础

Spring是什么? Spring是一个开源框架,最早由Rod Johnson创建,它解决的是业务逻辑层和其他各层的松耦合问题。 经过十几年的发展,Spring正在扩展其他的领域,如:移动开发、社交API集成、N...

这很耳东先生
2分钟前
0
0
面试系列-40个Java多线程问题总结

前言 这篇文章主要是对多线程的问题进行总结的,因此罗列了40个多线程的问题。 这些多线程的问题,有些来源于各大网站、有些来源于自己的思考。可能有些问题网上有、可能有些问题对应的答案也...

Ryan-瑞恩
15分钟前
0
0
微信分享的细节

分享的缩略图要求: 一、图片大小小于32k 二、图片的尺寸为 宽度 :128px 高度:128px 分享title 和 description 出现金额等 以上情况存在会导致触发分享按钮 但是页面没有反应...

Js_Mei
21分钟前
0
0
【2018.07.23学习笔记】【linux高级知识 Shell脚本编程练习】

1、编写shell脚本,计算1-100的和; #!/bin/bashsum=0for i in `seq 1 100`do sum=$[$sum+$i]doneecho $sum 2、编写shell脚本,要求输入一个数字,然后计算出从1到输入数字的和,要求...

lgsxp
23分钟前
0
0
xss攻防浅谈

导读 XSS (Cross-Site Script) 攻击又叫跨站脚本攻击, 本质是一种注入攻击. 其原理, 简单的说就是利用各种手段把恶意代码添加到网页中, 并让受害者执行这段脚本. XSS能做用户使用浏览器能做的...

吴伟祥
23分钟前
0
0
js回调的一次应用

function hideBtn(option) { if (option == 1) { $("#addBtn").hide(); $("#addSonBtn").hide(); }}$("body").on("click", "#selectBtn", function () {......

晨猫
30分钟前
0
0
C++_读写ini配置文件

1.WritePrivateProfileString:

一个小妞
30分钟前
0
0
通往阿里,BAT的50+经典Java面试题及答案解析(上)

Java是一个支持并发、基于类和面向对象的计算机编程语言。下面列出了面向对象软件开发的优点: 代码开发模块化,更易维护和修改。 代码复用。 增强代码的可靠性和灵活性。 增加代码的可理解性...

Java大蜗牛
30分钟前
1
0
数据库两大神器【索引和锁】

前言 只有光头才能变强 索引和锁在数据库中可以说是非常重要的知识点了,在面试中也会经常会被问到的。 本文力求简单讲清每个知识点,希望大家看完能有所收获 声明:如果没有说明具体的数据库...

Java3y
34分钟前
0
0
Application Express安装

Application Express安装文档 数据库选择和安装 数据库选择 Oracle建议直接12.2.0.1.0及以上的版本,12.1存在20618595bug(具体可参见官方文档) Oracle 12c 中安装oracle application expr...

youfen
46分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部