Spring AOP的实现——动态代理机制
来源:互联网 发布:安卓息屏录像软件 编辑:程序博客网 时间:2024/05/29 19:38
在java的动态代理中,有两个重要的类或者接口,一个是InvocationHandler(Interface)、另一个是Proxy(Class),这一个类和接口是实现动态代理所必须的。
InvocationHandler:每一个动态代理类都必须实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke方法来进行调用。
我们来看看invoke这个方法:
<span style="font-size:14px;">Object invoke(Object proxy,Method method,Object[] args)</span>proxy:指代我们所代理的真实对象
method:指代的是我们所要调用真实对象的某个方法的Method对象
args:指代的是调用真实对象某个方法时接收的参数
Proxy:这个类的作用就是用来动态的创建一个代理对象的类,其接受三个参数
<span style="font-size:14px;">public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException</span>loader:一个ClassLoader对象,定义了由哪个ClassLoader对象来生成的代理对象进行加载
interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了。
h:一个InvocationHandler对象,表示的是当我这个动态代理在调用方法的时候,会关联到哪一个InvocationHandler对象上
下面我们通过实例看看动态代理模式是什么:
首先,定义一个Subject接口,并且定义两个方法:
<span style="font-size:14px;">public interface Subject {public void rent();public void hello(String str);}</span>接着,定义一个类来实现上面的接口,这个类就是我们的真实对象:
<span style="font-size:14px;">public class RealSubject implements Subject{@Overridepublic void rent() {System.out.println("I want rent my house");}@Overridepublic void hello(String str) {System.out.println("hello:"+str);}}</span>下一步,定义动态代理类:
<span style="font-size:14px;">import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class Dynamicproxy implements InvocationHandler{//这就是我们代理的真实对象private Object subject;//构造方法,给我们要代理的真实对象赋值public Dynamicproxy(Object subject){this.subject = subject;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//在代理真实对象前我们可以添加一些自己的操作System.out.println("before rent house");System.out.println("Method:"+method);//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用method.invoke(subject, args);//在代理真实对象后我们可以添加一些自己的操作System.out.println("after rent house");return null;}}</span>最后,是Client类:
<span style="font-size:14px;">import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class Client {public static void main(String[] args) {//我们要代理的真实对象Subject realSubject = new RealSubject();//我们要代理哪个真实对象,就将该对象传进去,最后通过该真实的对象调用该方法InvocationHandler handler = new Dynamicproxy(realSubject);Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler);System.out.println(subject.getClass().getName());subject.rent();subject.hello("world");}}</span>控制台输出如下:
com.sun.proxy.$Proxy0
before rent house
Method:public abstract void com.by.proxyTest.Subject.rent()
I want rent my house
after rent house
before rent house
Method:public abstract void com.by.proxyTest.Subject.hello(java.lang.String)
hello:world
after rent house
首先,我们看看这条语句:
<span style="font-size:14px;">Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler); </span>为什么我们这里可以将其转化为Subject类型的对象?
原因在于newProxyInstance这个方法的第二个参数上,我们给代理对象提供什么接口,那么我们这个代理对象就会实现这个接口,这个时候我们可以将这个代理对象强制转换成Subject类型。
使用Proxy.newProxyInstance()创建的代理对象是在JVM上运行时动态产生的一个对象,它并不是InvocationHandler类型,也不是我们定义的那组接口的类型,而是在运行时动态产生的一个对象。并且命名方式是以$开头的,proxy中最后一个数字表示对象的标号。
subject.rent();subject.hello("world");这里是通过对象来调用实现的那种接口中的方法,这个时候程序就会跳转到由这个代理对象关联到的handler中的invoke方法去执行,而我们这个handler对象又接受了一个RealSubject类型的参数,表示我要代理的就是这个真实对象,所以此时就会调用handler中的invoke方法去执行:
<span style="font-size:14px;">import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class Dynamicproxy implements InvocationHandler{//这就是我们代理的真实对象private Object subject;//构造方法,给我们要代理的真实对象赋值public Dynamicproxy(Object subject){this.subject = subject;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//在代理真实对象前我们可以添加一些自己的操作System.out.println("before rent house");System.out.println("Method:"+method);//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用(通过烦反射执行某个类的某方法)method.invoke(subject, args);//在代理真实对象后我们可以添加一些自己的操作System.out.println("after rent house");return null;}}</span>我们看到,在真正通过代理对象来调用真实对象的方法的时候,我们可以在该方法前后添加自己的一些操作,同时我们看到我们这个method对象是这样:
<span style="font-family:Microsoft YaHei;font-size:14px;">public abstact void com.xiaoluo.dynamicproxy.Subject.rent()public abstract void com.xiaoluo.dynamicproxy.Subject.hello(java.lang.String)</span>正好就是我们的Subject接口中的两个方法,这也就证明了当我通过代理对象来调用方法的时候,起实际就是委托由其关联到的handler对象的invoke方法中来调用,并不是自己来真实调用,而是通过代理的方式来调用。
动态代理的作用:
主要用来做方法的增强,让你可以在不修改源码的情况下,增强一些方法,在方法执行前后做任何你想做的事情(甚至根本不去执行这个方法),因为在InvocationHandler的invoke这个方法中,你可以直接获取正在调用方法对应的Method对象,具体应用,比如,添加日志,做事物控制等。
- Spring AOP的实现——动态代理机制
- Spring AOP——java的动态代理机制详解
- Spring AOP中的动态代理实现机制
- Spring AOP的实现机制(一)----- 动态代理
- Spring 容器AOP的实现原理——动态代理
- Spring 容器AOP的实现原理——动态代理
- Spring 容器AOP的实现原理——动态代理
- Spring AOP原理——Java中的动态代理机制
- Spring AOP 动态代理机制
- Spring AOP 动态代理机制
- AOP的简单实现---动态代理机制
- Spring AOP 的实现原理----动态代理
- 动态代理实现Spring Aop
- Spring动态代理,aop 注解实现aop
- Spring—AOP两种代理机制对比(JDK和CGLib动态代理)
- Spring AOP中的动态代理机制
- spring的AOP学习2——动态代理
- Spring AOP——Java动态代理
- Leetcode 96. Unique Binary Search Trees (Medium) (cpp)
- Content Provider 使用
- NPM 使用介绍
- java代码操作zip文件--读取zip文件
- Cookie创建-获取-持久化、自动登录、购物记录、作用路径
- Spring AOP的实现——动态代理机制
- Android自定义ViewGroup(二)之WaterfallLayout
- nginx限制ip访问 nginx访问权限
- VS2010/MFC编程入门之二十八(常用控件:列表视图控件List Control 上)
- 遍历Map
- HDU:5253 连接的管道(最小生成树+变形处理)
- HDU 3065 (AC自动机水题)
- ubuntu下安装libnet、libpcap、libnids等环境
- VS2010/MFC编程入门之二十九(常用控件:列表视图控件List Control 下)