Spring 代理模式及AOP基本术语
一、代理模式:
静态代理、动态代理
动态代理和静态代理区别??
解析:静态代理需要手工编写代理类,代理类引用被代理对象。
动态代理是在内存中构建的,不需要手动编写代理类
代理的目的:是为了在原有的方法上进行增强。
动态代理的两种方式:JDK动态代理与CGLIB代理
默认情况下,Spring AOP的实现对于接口来说就是使用的JDK的动态代理来实现的,而对于类的代理使用CGLIB来实现。
二、静态代理
①定义接口 Subject并添加方法:
|
1
2
3
|
public interface Subject {public void request();} |
② 定义接口的实现类 RealSubject并实现该接口,重写方法--被代理对象
|
1
2
3
4
5
6
|
public class RealSubject implements Subject{ public void request() { System.out.println("真实主题内容"); } |
③定义接口的实现类ProxySubject并实现该接口重写方法。自定义属性RealSubject,调用request方法,在这里进行增强
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public class ProxySubject implements Subject{private RealSubject real; public void request() { System.out.println("===before==="); //调用request() real.request(); System.out.println("===after==="); } public RealSubject getReal() { return real; } public void setReal(RealSubject real) { this.real = real; } |
④测试类:
分别创建出被代理对象和代理对象,执行方法
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class ProxyTest {//静态代理 @Test public void test01(){ //准备一个真实主题,被代理对象 RealSubject real=new RealSubject(); //创建一个代理对象 ProxySubject proxy=new ProxySubject(); proxy.setReal(real); proxy.request();} |
执行效果:

可以看出静态代理类有一个缺点:当如果接口加一个方法,所有的实现类和代理类里都需要做个实现。这就增加了代码的复杂度。动态代理就可以避免这个缺点。
三、动态代理
1.1、JDK动态代理:
本质:在内存中构建接口实现类
特点:被代理对象必须有接口
JDK提供了java.lang.reflect.Proxy类来实现动态代理的,可通过它的newProxyInstance来获得代理实现类。同时对于代理的接口的实际处理,是一个java.lang.reflect.InvocationHandler,它提供了一个invoke方法供实现者提供相应的代理逻辑的实现。可以对实际的实现进行一些特殊的处理,像Spring AOP中的各种advice。下面来看看如何使用。
定义接口IUserDao:
|
1
2
3
4
5
6
|
public interface IUserDao {public String add();public String edit();} |
定义接口实现类,实现某接口,并重写该方法:
|
1
2
3
4
5
6
7
8
9
10
11
|
public String add() { System.out.println("==add==="); return "我是add"; }public String edit() { System.out.println("===edit==="); return "edit"; } |
测试类:(重点)

实现效果:

可以由源码可见如何生成代理类的:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException { if (h == null) { throw new NullPointerException(); } final Class<?>[] intfs = interfaces.clone(); final SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } // 这里是生成class的地方 Class<?> cl = getProxyClass0(loader, intfs); // 使用我们实现的InvocationHandler作为参数调用构造方法来获得代理类的实例 try { final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) { return AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { return newInstance(cons, ih); } }); } else { return newInstance(cons, ih); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString()); } }其中newInstance只是调用Constructor.newInstance来构造相应的代理类实例,这里重点是看getProxyClass0这个方法的实现: private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { // 代理的接口数量不能超过65535 if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } // JDK对代理进行了缓存,如果已经存在相应的代理类,则直接返回,否则才会通过ProxyClassFactory来创建代理 return proxyClassCache.get(loader, interfaces); } |
可以看到,动态生成的代理类有如下特性:
1) 继承了Proxy类,实现了代理的接口,由于java不能多继承,这里已经继承了Proxy类了,不能再继承其他的类,所以JDK的动态代理不支持对实现类的代理,只支持接口的代理。
2) 提供了一个使用InvocationHandler作为参数的构造方法。
3) 生成静态代码块来初始化接口中方法的Method对象,以及Object类的equals、hashCode、toString方法。
4) 重写了Object类的equals、hashCode、toString,它们都只是简单的调用了InvocationHandler的invoke方法,即可以对其进行特殊的操作,也就是说JDK的动态代理还可以代理上述三个方法。
1.2、cglib动态代理:
JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要cglib了。cglib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用
创建被代理的类:
|
1
2
3
4
5
|
public class UserService {public void delete(){ System.out.println("delete ok!!!");}} |
测试类:(重点)
该类实现了创建子类的方法与代理的方法。SuperClass方法通过入参即父类的字节码,通过扩展父类的class来创建代理对象。intercept()方法拦截所有目标类方法的调用,obj表示目标类的实例,method为目标类方法的反射对象,args为方法的动态入参,proxy为代理类实例。proxy.invoke(obj, args)通过代理类调用父类中的方法 !

实现效果:

四、AOP基本术语:
AOP Aspect Oriented Programming 面向切面编程
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
面向对象编程是从【静态角度】考虑程序的结构,而面向切面编程是从【动态角度】考虑程序运行过程。
AOP底层,就是采用【动态代理】模式实现的。采用了两种代理:JDK动态代理和CGLIB动态代理。
基本术语(一些名词):
(1)切面(Aspect)
切面泛指[*交叉业务逻辑*]。事务处理和日志处理可以理解为切面。常用的切面有通知(Advice)与顾问(Advisor)。实际就是对主业务逻辑的一种增强。
(2)织入(Weaving)
织入是指将切面代码插入到目标对象的过程。代理的invoke方法完成的工作,可以称为织入。
(3) 连接点(JoinPoint)
连接点是指可以被切面织入的方法。通常业务接口的方法均为连接点
(4)切入点(PointCut)
切入点指切面具体织入的方法
注意:被标记为final的方法是不能作为连接点与切入点的。因为最终的是不能被修改的,不能被增强的。
(5)目标对象(Target)
目标对象指将要被增强的对象。即包含主业务逻辑的类的对象。
(6)通知(Advice)
通知是切面的一种实现,可以完成简单的织入功能。通知定义了增强代码切入到目标代码的时间点,是目标方法执行之前执行,还是执行之后执行等。切入点定义切入的位置,通知定义切入的时间。
(7)顾问(Advisor)
顾问是切面的另一种实现,能够将通知以更为复杂的方式织入到目标对象中,是将通知包装为更复杂切面的装配器。
Spring 代理模式及AOP基本术语的更多相关文章
- Spring代理模式及AOP基本术语
一.代理模式: 静态代理.动态代理 动态代理和静态代理区别?? 解析:静态代理需要手工编写代理类,代理类引用被代理对象. 动态代理是在内存中构建的,不需要手动编写代理类 代理的目的:是为了在原有的方法 ...
- 这一次搞懂Spring代理创建及AOP链式调用过程
文章目录 前言 正文 基本概念 代理对象的创建 小结 AOP链式调用 AOP扩展知识 一.自定义全局拦截器Interceptor 二.循环依赖三级缓存存在的必要性 三.如何在Bean创建之前提前创建代 ...
- 代理模式与AOP
代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联 ...
- 代理模式——用AOP测试业务层方法的执行时间
代理模式 对代理模式的理解,通过http://www.runoob.com/design-pattern/proxy-pattern.html 对AOP的代理模式,参考https://www.cnbl ...
- Spring代理模式(jdk动态代理模式)
有动态代理和静态代理: 静态代理就是普通的Java继承调用方法. Spring有俩种动态代理模式:jdk动态代理模式 和 CGLIB动态代理 jdk动态代理模式: 代码实现: 房东出租房子的方法(继承 ...
- Spring代理模式(CGLIB动态代理模式)
jdk动态代理和CGLIB动态代理 没什么太大的区别,CGLIB动态代理不需要接口,但是需要导入jar包. 房东出租房子的方法: package com.bjsxt.proxy2; public cl ...
- Spring框架学习05——AOP相关术语详解
1.Spring AOP 的基本概述 AOP(Aspect Oriented Programing)面向切面编程,AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(性能监视.事务管理.安全检查 ...
- 代理模式应用-AOP事务(转)
https://jinnianshilongnian.iteye.com/blog/14872351.预备知识 aop概念请参考[http://www.iteye.com/topic/1122401] ...
- spring代理模式 service远程调用,插件执行
最近,研究了一下平台远程调用的过程,和service层插件执行的原理,记录一下. 1.远程service调用过程 首先看一下类的继承结构 封装调用处理过程 封装service调用接口 封装servic ...
随机推荐
- 欢迎使用 MWeb
首先介绍一下 MWeb 是什么,MWeb 是专业的 Markdown 写作.记笔记.静态博客生成软件.MWeb 使用的是 Github Flavored Markdown 语法,在使用 MWeb 前, ...
- Hibernate(2)——Hibernate的实现原理总结和对其模仿的demo
俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及的知识点总结如下: 开源框架的学习思路(个人总结) Hibernate的运行原理总结 Hibernate实现原理中的两个主要技术 ...
- SQL Tuning 基础概述03 - 使用sql_trace和10046事件跟踪执行计划
1.使用sql_trace跟踪执行计划 1.1 当前session跟踪: alter session set sql_trace = true; //开始sql_trace alter session ...
- 基于 WebSocket 实现 WebGL 3D 拓扑图实时数据通讯同步(二)
我们上一篇<基于 WebSocket 实现 WebGL 3D 拓扑图实时数据通讯同步(一)>主要讲解了如何搭建一个实时数据通讯服务器,客户端与服务端是如何通讯的,相信通过上一篇的讲解,再配 ...
- 把UI图里的小图标制作成icon font
一个交互比较多的UI图里面可能会有很多小图标,一般可用sprites图将多个小图标弄成一张大图,或者其它的办法,各种方法的比较可参见博主的另外一篇博客使用css3新属性clip-path制作小图标,本 ...
- 前端开发:setTimeout与setInterval 定时器与异步循环数组
前端开发:setTimeout与setInterval 定时器与异步循环数组 前言: 开通博客园三个月以来,随笔记录了工作中遇到的大大小小的难题,也看过无数篇令人启发的文章,我觉得这样的环境是极好的, ...
- ubuntu 入门
ubuntu 系统设置不全sudo apt-get install ubuntu-desktop uget aria2:下载工具http://www.xitongzhijia.net/xtjc/201 ...
- 记录一次bug解决过程:resultType和手动开启事务
一.总结 二.BUG描述:MyBatis中resultType使用 MyBatis中的resultType类似于入参:parameterType.先看IDCM项目中的实际使用案例代码,如下: // L ...
- 来玩Play框架01 简介
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 说到网络框架,Ruby的Ruby on Rail和Python的Django都相当 ...
- mysql can't create threads in threadpool
最近,我们在券商端的mysql运行一段时间后,发生mysql can't create threads in threadpool,如下所示: 据官网一个报告显示,目测是一个bug,内存紧张导致,那天 ...