动态代理
来源:互联网 发布:手机淘宝详情页大小 编辑:程序博客网 时间:2024/05/17 23:39
动态代理
1.动态代理概述
代理模式是Java设计模式中的一种,其特征为代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。
代理类与委托类之间通常存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现业务,而是通过调用委托类对象的相关方法来提供具体业务。
通过反射动态生成代理对象,通过代理对象调用委托类的方法.
作用:代理类会对委托类的方法进行过滤.
在Java中的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和接口可以生成JDK动态代理或动态代理对象。
按照代理的创建时间不同,可以分为两种:
Ø 静态代理:手动创建,再对其编译。在程序运行前,代理类的.class文件就已经存在。
Ø 动态代理:在程序运行时,通过反射机制动态创建而成。
2.动态代理的原理
3.Proxy代理类
Proxy类是Java的java.lang.reflect包下提供的,该类用于创建动态代理类和代理对象的静态方法,它也是所有动态代理类的父类。
如果在程序中为一个或多个接口动态地生成实现类,就可以用Proxy类来创建动态代理类;
如果需要为一个或多个接口动态地创建实例,也可以使用Proxy类来创建动态代理实例。
static InvocationHandler
getInvocationHandler
(Object proxy)
返回指定代理实例的调用处理程序。
static Class<?>
getProxyClass
(ClassLoader loader,Class<?>... interfaces)
返回代理类的 java.lang.Class
对象,并向其提供类加载器和接口数组。
static boolean
isProxyClass
(Class<?> cl)
当且仅当指定的类通过 getProxyClass
方法或 newProxyInstance
方法动态生成为代理类时,返回 true。
static Object
newProxyInstance
(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
Ø static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces):
创建一个动态代理类所对应的Class对象,该代理类将实现interfaces所指定的多个接口。第一个ClassLoader参数指定生成动态代理类的类加载器。
Ø static Object newProxyInstance(ClassLoaderloader, Class<?>[] interfaces, InvocationHandler h):
直接创建一个动态代理对象,该代理对象的实现类实现了interfaces指定的系列接口,执行代理对象的每个方法时都会被替换执行InvocationHandler对象的invoke()方法。
4.InvocationHandler
InvocationHandler接口提供了invoke()方法,用于替换代理对象的每一个方法。
真实业务类可以通过代理类对象调用InvocationHandler接口提供的invoke()方法,来替代调用委托类的真实方法。
invoke()方法:通过代理对象去执行委托类的方法 , 即代理对象通过该方法去执行委托类的方法以下是InvocationHandler的API内容:
Object
invoke
(Object proxy,Method method, Object[] args)
在代理实例上处理方法调用并返回结果。
Ø Object invoke(Object proxy, Method method, Object[] args):
在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。
² 参数proxy:表示代理类对象,也就是Proxy.newProxyInstance()方法返回的对象,通常用不上。
² 参数method:表示当前被调用方法的反射对象,
² 参数args:表示调用目标方法时传入的实参。
5.实现动态代理
* newProxyInstance()
invocationHandler接口:
* invoke(proxy对象,Method,对应方法的实参)
利用Java提供的Proxy类和InvocationHandler接口来生成动态代理类或动态代理对象,具体实现步骤如下:
1.定义一个业务接口,该接口提供具体业务方法的定义。
public interface Person {void sayMe();void sayHello(String name);}
2.定义一个InvocationHandler接口的实现类,并重写invoke()方法。
public class MyInvocationHandler implements InvocationHandler {/** * 执行动态代理对象的所有方法时,都会被替换成执行下面的invoke()方法. * * 参数proxy:代表动态代理对象. * * 参数method:代表正在执行的方法. * * 参数args:代表调用目标方法时传入的实参. */@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {System.out.println("---正在执行的方法: "+method);if(args == null){System.out.println("当前调用的方法没有参数.");}else{System.out.println("当前调用的方法需要传入的实参为:");for (Object val : args) {System.out.println(val);}}return null;}}
3. 编写一个用于测试动态代理的测试类。
public class ProxyTest {public static void main(String[] args) {// 创建一个InvocationHandler对象InvocationHandler handler = new MyInvocationHandler();// 通过Proxy类使用指定的InvocationHandler来生成动态代理对象Person p = (Person)Proxy.newProxyInstance(Person.class.getClassLoader(), new Class[]{Person.class}, handler);// 调用动态代理对象的业务方法p.sayMe();p.sayHello("张无忌");}}
6、动态代理的作用
阻止调用对应委托类的方法.
修改委托类方法的返回值.
通过Java提供的Proxy类和InvocationHandler接口生成的动态代理类,可以阻止调用委托类的方法、过滤参数及修改对应方法的返回值等作用。
实现业务接口方法的实现类即委托类,具体操作如下:
1、创建一个实现类,实现Person接口,并重写业务方法。
public class Fanbingbing implements Person {@Overridepublic void sayMe() {System.out.println("我真的是范冰冰哦!");}@Overridepublic String sayHello(String name) {System.out.println("你好:"+name+",我等你很久了...");return "我终于见到范冰冰啦!";}}
2、编写一个用于测试动态代理的测试类。
public class FanbingbingTest {public static void main(String[] args) {Person p = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(),Fanbingbing.class.getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method,Object[] args) throws Throwable {// 通过method的getName()方法获取业务方法名,进行阻止.if (method.getName().equals("sayMe")) {System.out.println("你想多了,哪那么容易见到啊!");return null;}// 通过args获取实参,进行修改if(method.getName().equals("sayHello")){String name = (String)args[0];method.invoke(Class.forName("app.java.proxy.Fanbingbing").newInstance(), "某局长");}// 修改返回值if(method.getName().equals("sayHello")){return "都是假的!";}return null;}});p.sayMe();p.sayHello("张无忌");}}
Star:
package app.java.proxy;public interface Star {public void song(String name);public String movie();}
Fbb:
package app.java.proxy;public class Fbb implements Star {public void song(String name) {System.out.println(name+" song........");}public String movie() {System.out.println("movie........");return "武媚娘传奇,禁播了!!!";}}
ProxyTest:
package app.java.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class ProxyTest {public static void main(String[] args) {/** * Proxy类的newProxyInstance(ClassLoader,Class[])方法: * * 获取对应委托类的代理对象. * * 参数一:指定对应委托类的类加载器. * * 参数二:指定委托类的Class * * 参数三:InvocationHandler的实例(重写invoke) * * 动态代理的作用: * * 不需要得到对应委托类的对象. * * 通过代理类对象,对委托类的方法进行过滤(修改)等. */Star fbb = (Star)Proxy.newProxyInstance(Star.class.getClassLoader(), Fbb.class.getInterfaces(), new InvocationHandler() {/** * invoke(Object proxy, Method method, Object[] args) * * 该方法的作用:调用对应的委托类的方法. * * 参数一:返回的是代理类对象. * * 参数二:返回的是对应委托类方法的Method类型对象. * * 参数三:返回的是对应委托类方法接收的实参. */public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {// 可以获取到对应委托类方法的参数. /*String name = (String)args[0];if(name.equals("zhangwuji")){method.invoke(new Fbb(), "zhouzhiruo");}*/// 阻止调用对应委托类的方法/*String methodName = method.getName();if(methodName.equals("movie")){System.out.println("范冰冰最近太累了,不能拍电影,改唱歌了!");}*/// 修改委托类方法的返回值String methodName = method.getName();if(methodName.equals("movie")){return "武媚娘传奇,重播了!!!";}return null;}});//fbb.song("zhangwuji");String value = fbb.movie();System.out.println(value);}}
ProxyTest2:
package app.java.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class ProxyTest2 {public static void main(String[] args) {Star star = (Star)Proxy.newProxyInstance(Star.class.getClassLoader(), Fbb.class.getInterfaces(), new InvocationHandler() {public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {return method.invoke(new Fbb(), args);}});System.out.println(star);star.movie();}}
- 代理-->静态代理&动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- ORACLE常用的函数总结:
- 丑书 Ugly number
- Linux 安装本地Yum源
- 关于jquery ajax请求发了,返回值也有,但是却无法进去ajax的success回调函数
- 日志级别
- 动态代理
- MyEclipse安装和卸载SVN
- 线程
- View.bringToFront()方法 ViewGroup.bringChildToFront(View child)将view显示在视图的最顶层
- csdn成为了我生活的一部分
- ts 协议解析
- 用 XML 自定义边框效果(左边框有颜色)
- 微信小程序开发新增5大功能
- Ubuntu下安装MySQL