Spring核心框架 - AOP之动态代理机制
动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。
一.相关类及其方法:
java.lang.reflect.Proxy,
Proxy 提供用于创建动态代理类和实例的静态方法.
newProxyInstance()返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序
java.lang.reflect.InvocationHandler,
InvocationHandler 是代理实例的调用处理程序实现的接口。
invoke()在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。
具体实例:联谊会或者相亲
1、寻找GF接口
- package com.aop;
- /**
- * 寻找GF接口
- *
- * @author Anndy
- */
- public interface FindGFInterface {
- /**
- * 寻找GF方法
- */
- public void findGF();
- }
2、寻找GF实现类
- package com.aop;
- /**
- * Anndy寻找GF实现类
- *
- * @author Anndy
- */
- public class AnndyFindGFInterfaceImpl implements FindGFInterface {
- public void findGF() {
- System.out.println("Anndy go to find GF!");
- }
- }
3、代理类处理
- package com.aop;
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- /**
- * 打扮帅点,去约会
- *
- * @author Anndy
- */
- public class ReadyInvocationHandler implements InvocationHandler {
- private Object anndy = null;
- public ReadyInvocationHandler(Object realSubject) {
- this.anndy = realSubject;
- }
- /**
- * 动态代理类$Proxy0调用FindGF方法时会调用它自己的FindGF方法,
- * 而它自己的FindGF方法里面调用的是super.h.invoke(this, , ),也就是父类Proxy的h的invoke方法,
- * 实际上就是ReadyInvocationHandler类的invoke方法。 所以invoke(Object proxy, Method
- * m,Object[] args)中的proxy实际上就是动态代理类$Proxy0,
- * 在这里不能将其强转成AnndyFindGFInterfaceImpl然后调用它的FindGF方法,会出现死循环
- */
- public Object invoke(Object proxy, Method m, Object[] args) {
- Object result = null;
- try {
- System.out.println(proxy.getClass().getSimpleName());
- System.out.println("Anndy找女朋友,代理人给他打扮了打扮。");
- result = m.invoke(anndy, args);
- } catch (Exception ex) {
- System.exit(1);
- }
- return result;
- }
- }
4、动态代理实现
- package com.aop;
- import java.lang.reflect.Proxy;
- /**
- * 联谊会现场
- *
- * @author Anndy
- */
- public class SceneOfSodality {
- public static void main(String args[]) {
- /**
- * 得到AnndyFindGFInterfaceImpl这个类的一个代理类,
- * 同时为代理类绑定了一个处理类ReadyInvocationHandler。
- * 每次调用AnndyFindGFInterfaceImpl这个子类的findGF方法时,
- * 并不是anndy这个AnndyFindGFInterfaceImpl类的实例去调用,
- * 而是这个AnndyFindGFInterfaceImpl的代理类ReadyInvocationHandler去调用它自己的invoke方法
- */
- // 实例化对象
- FindGFInterface anndy = new AnndyFindGFInterfaceImpl();
- /**
- * java中的动态代理实现 第一步,我们要有一个接口,还要有一个接口的实现类,而这个实现类就是我们要代理的对象,
- * 所谓代理就是在调用实现类的方法时,可以在方法执行前后做额外的工作,这个就是代理。
- * 第二步,我们要自己写一个在代理类的方法执行时,能够做额外工作的类,而这个类必须继承InvocationHandler接口,
- * 因为代理类的实例在调用实现类的方法的时候,不会调真正的实现类的这个方法,
- * 而是转而调用这个类的invoke方法(继承时必须实现的方法),在这个方法中你可以调用真正的实现类的这个方法。
- * 第三步,在要用代理类的实例去调用实现类的方法的时候,写出下面两段代码。
- */
- FindGFInterface proxy = (FindGFInterface) Proxy.newProxyInstance(anndy
- .getClass().getClassLoader(), anndy.getClass().getInterfaces(),
- new ReadyInvocationHandler(anndy));
- proxy.findGF();
- }
- }
到此,上面是整个动态代理的过程。
二、动态代理步骤总结
1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(...);
2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类Class clazz = Proxy.getProxyClass(classLoader,new Class[]{...});
3、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
4、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));为了简化对象创建过程,Proxy类中的newInstance方法封装了2~4,只需两步即可完成代理对象的创建。生成的ProxySubject继承Proxy类实现Subject接口,实现的Subject的方法实际调用处理器的invoke方法,而invoke方法利用反射调用的是被代理对象的的方法(Object result=method.invoke(proxied,args))。
三、附录$Proxy0类的源码
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- import java.lang.reflect.UndeclaredThrowableException;
- public final class $Proxy0 extends Proxy implements Manager {
- private static Method m1;
- private static Method m0;
- private static Method m3;
- private static Method m2;
- static {
- try {
- m1 = Class.forName("java.lang.Object").getMethod("equals",
- new Class[] { Class.forName("java.lang.Object") });
- m0 = Class.forName("java.lang.Object").getMethod("hashCode",
- new Class[0]);
- m3 = Class.forName("com.ml.test.Manager").getMethod("modify",
- new Class[0]);
- m2 = Class.forName("java.lang.Object").getMethod("toString",
- new Class[0]);
- } catch (NoSuchMethodException nosuchmethodexception) {
- throw new NoSuchMethodError(nosuchmethodexception.getMessage());
- } catch (ClassNotFoundException classnotfoundexception) {
- throw new NoClassDefFoundError(classnotfoundexception.getMessage());
- }
- }
- public $Proxy0(InvocationHandler invocationhandler) {
- super(invocationhandler);
- }
- @Override
- public final boolean equals(Object obj) {
- try {
- return ((Boolean) super.h.invoke(this, m1, new Object[] { obj }))
- .booleanValue();
- } catch (Throwable throwable) {
- throw new UndeclaredThrowableException(throwable);
- }
- }
- @Override
- public final int hashCode() {
- try {
- return ((Integer) super.h.invoke(this, m0, null)).intValue();
- } catch (Throwable throwable) {
- throw new UndeclaredThrowableException(throwable);
- }
- }
- public final void modify() {
- try {
- super.h.invoke(this, m3, null);
- return;
- } catch (Error e) {
- } catch (Throwable throwable) {
- throw new UndeclaredThrowableException(throwable);
- }
- }
- @Override
- public final String toString() {
- try {
- return (String) super.h.invoke(this, m2, null);
- } catch (Throwable throwable) {
- throw new UndeclaredThrowableException(throwable);
- }
- }
- }
Spring核心框架 - AOP之动态代理机制的更多相关文章
- Spring核心框架 - AOP的原理及源码解析
一.AOP的体系结构 如下图所示:(引自AOP联盟) 层次3语言和开发环境:基础是指待增加对象或者目标对象:切面通常包括对于基础的增加应用:配置是指AOP体系中提供的配置环境或者编织配置,通过该配置A ...
- Spring核心框架 - AOP的起源及介绍
一.AOP技术起源 AOP技术的诞生并不算晚,早在1990年开始,来自Xerox Palo Alto Research Lab(即PARC)的研究人员就对面向对象思想的局限性进行了分析.他们研究出了一 ...
- spring基础概念AOP与动态代理理解
一.代理模式 代理模式的英文叫做Proxy或Surrogate,中文都可译为”代理“,所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一 ...
- 【spring 4】AOP:动态代理
一.动态代理简介 动态代理与普通代理相比较,最大的好处是接口中声明的所有方法都被转移到一个集中的方法中处理(invoke),这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那 ...
- Spring学习(二)—— java的动态代理机制
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
- 浅谈Spring的AOP实现-动态代理
说起Spring的AOP(Aspect-Oriented Programming)面向切面编程大家都很熟悉(Spring不是这次博文的重点),但是我先提出几个问题,看看同学们是否了解,如果了解的话可以 ...
- 【Java EE 学习 51】【Spring学习第三天】【cglib动态代理】【AOP和动态代理】【切入点表达式】
一.cglib动态代理 1.简介 (1)CGlib是一个强大的,高性能,高质量的Code生成类库.它可以在运行期扩展Java类与实现Java接口. (2) 用CGlib生成代理类是目标类的子类. (3 ...
- 详解Java动态代理机制
之前介绍的反射和注解都是Java中的动态特性,还有即将介绍的动态代理也是Java中的一个动态特性.这些动态特性使得我们的程序很灵活.动态代理是面向AOP编程的基础.通过动态代理,我们可以在运行时动态创 ...
- 基于 JDK 的动态代理机制
『动态代理』其实源于设计模式中的代理模式,而代理模式就是使用代理对象完成用户请求,屏蔽用户对真实对象的访问. 举个最简单的例子,比如我们想要「FQ」访问国外网站,因为我们并没有墙掉所有国外的 IP,所 ...
随机推荐
- Asp.Net 之 下载文件的常用方式
1.直接使用Response.TransmitFile(filename)方法 protected void Button_Click(object sender, EventArgs e) { /* ...
- 多线程NSOperation
NSOperation(经常使用): 1.为什么会有NSOperation?弥补gcd的一些问题:1)下载为例子:如果gcd放到队列中的block操作面对网络有问题,block之外无法取消bloc ...
- 对于 NSLayoutConstraint 不执行动画的处理:
在开发中 我们有时候需要改变某个空间的约束条件 也就是更改NSLayoutConstraint的值 (比如说我想在键盘顶部增加一个工具栏 让工具栏随着键盘的位置变化而变化 有一个动画效果)但是发 ...
- bootstrap在iis中发布后无法看到图标,字体样式
因为框架使用了字体文件来显示矢量的图标,为了能在IIS上正常显示图标,可以通过增加iis的MIME-TYPE来支持图标字体文件:
- 配置LINUX为路由
配置:关闭防火墙 linux1 地址1: 192.168.10.10/24 地址2:192.168.20.10/24(不指定网关,做为路由,自己就是网关) linux2 地址1: 192. ...
- 业界最有价值的 ASP.NET 博文汇总
ASP.NET凭借它丰富的控件,强大的适应性及良好的封装性,成为业界开发的一门巨匠,它大大缩短了网站开发的时间,降低开发成本.并且可以运行在Web应用软件开发者的全部平台上.本电子书汇集了业界最有价值 ...
- dedecms获取栏目下的频道列表
可以使用: {dede:channelartlist}标签 使用方法: {dede:channelartlist row='6'} <dl> <dt><a href= ...
- List集合即其遍历
1. 首先List<E>集合继承与Collection<E>,是一个接口. ① Collection (集合框架是JDK1.2版本出现的) ② list:是有序的,元素可 ...
- 基于spark实现表的join操作
1. 自连接 假设存在如下文件: [root@bluejoe0 ~]# cat categories.csv 1,生活用品,0 2,数码用品,1 3,手机,2 4,华为Mate7,3 每一行的格式为: ...
- hdoj1584 蜘蛛牌 (区间型动态规划)
hdoj1584 分析: f[i][j] 表示 把一串牌 牌 i 到 j 摞为一摞时 所花费最少的步数. d[i][j] 表示把牌 i 挪到牌 j 上时需要走的步数(最初给的状态). 以一串牌 3~8 ...