Java动态代理模式怎么实现
Java动态代理模式怎么实现
这篇文章主要介绍“Java动态代理模式怎么实现”,在日常操作中,相信很多人在Java动态代理模式怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java动态代理模式怎么实现”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
1. Overview
Java在java.lang.reflect包下,定义了自己的代理。利用这个包下的类,我们可以在运行时动态地创建一个代理类,实现一个或多个接口。并将方法的调用转发到你所指定的类。因为实际代理是在运行时创建的,所以称为:动态代理。
Proxy:完全由java产生的,而且实现了完整的subject接口。
InvocationHandler:Proxy上的任何方法调用都会被传入此类,InvocationHandler控制对RealSubject的访问。
因为Java已经帮助我们创建了Proxy类,我们需要有办法告诉Proxy类你要做什么,我们不能像以前一样把代码写入到Proxy类中,因为Proxy类不是我们实现的。那么我们应该放在哪里?放在InvocationHandler类中,InvocationHandler类是响应代理的任何调用。我们可以吧InvocationHandler想成是代理收到方法调用后,请求做实际工作的对象。
2. java.lang.reflect.InvocationHandler
被代理实例所实现的一个接口,内部只有一个invoke()方法,签名如下;
Java代码
publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)
当代理的方法被调用的时候,代理就会把这个调用转发给InvocationHandler,也就会调用它的invoke()方法。
3. java.lang.reflect.Proxy
提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类,我们经常使用的静态方式是:
Java代码
newProxyInstance(ClassLoaderloader,Class[]interfaces,InvocationHandlerh)
4. 示例:
情形:自己可以查看修改姓名性别,但是不能修改rate。他人可以查看姓名,性别以及修改rate,但是不能修改姓名性别。
4.1 定义一个接口:
Java代码
publicinterfacePerson{StringgetName();StringgetGender();voidsetName(Stringname);voidsetGender(Stringgender);voidsetRate(intrate);intgetRate();}
4.2 定义实现Person接口类
Java代码
publicclassPersonImplimplementsPerson{Stringname;Stringgender;Stringinterests;intrate;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicStringgetGender(){returngender;}publicvoidsetGender(Stringgender){this.gender=gender;}publicStringgetInterests(){returninterests;}publicvoidsetInterests(Stringinterests){this.interests=interests;}publicintgetRate(){returnrate;}publicvoidsetRate(intrate){this.rate=rate;}
4.3 定义OwnerInvocationHandler类,表示如果为本人,则可以进行修改查看姓名性别。
Java代码
publicclassOwnerInvocationHandlerimplementsInvocationHandler{privatePersonpersonBean;publicOwnerInvocationHandler(PersonpersonBean){this.personBean=personBean;}@OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsIllegalAccessException{try{if(method.getName().startsWith("get")){//如果方法名为get,就调用person类内的get相应方法returnmethod.invoke(personBean,args);}elseif(method.getName().equals("setRate")){//如果方法是setRate,则抛出异常thrownewIllegalAccessException("accessdeny");}elseif(method.getName().startsWith("set")){//如果为set,就调用person类内的set相应方法returnmethod.invoke(personBean,args);}else{System.out.println("nonmethodinvoke");}}catch(InvocationTargetExceptione){e.printStackTrace();}returnnull;}}
4.4 定义NonInvocationHandler类,表示如果不为本人,则可以进行查看姓名性别和修改rate。
Java代码
publicclassNonInvocationHandlerimplementsInvocationHandler{//privatePersonperson;publicNonInvocationHandler(Personperson){this.person=person;}@OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{if(method.getName().startsWith("setRate")){returnmethod.invoke(person,args);}elseif(method.getName().startsWith("get")){returnmethod.invoke(person,args);}else{System.out.println("nonmethodinvoke");returnnull;}}}
4.5 测试类MyDynamicProxy
Java代码
publicclassMyDynamicProxy{publicPersongetOwnerPersonBeanProxy(Personperson){return(Person)Proxy.newProxyInstance(person.getClass().getClassLoader(),person.getClass().getInterfaces(),newOwnerInvocationHandler(person));}publicPersongetNonPersonBeanProxy(Personperson){return(Person)Proxy.newProxyInstance(person.getClass().getClassLoader(),person.getClass().getInterfaces(),newNonInvocationHandler(person));}publicstaticvoidmain(String[]args){MyDynamicProxymdp=newMyDynamicProxy();mdp.test();}publicvoidtest(){//Personperson=getPersonBeanFromDB1();PersonpersonProxy=getOwnerPersonBeanProxy(person);System.out.println(personProxy.getName());try{personProxy.setRate(2);}catch(Exceptione){System.out.println("cannotsetRate");}//Personperson1=getPersonBeanFromDB1();PersonpersonProxy2=getNonPersonBeanProxy(person1);System.out.println(personProxy2.getName());personProxy2.setRate(2);System.out.println(personProxy2.getRate());}privatePersongetPersonBeanFromDB1(){Personpb=newPersonImpl();pb.setName("remy");pb.setGender("girl");pb.setRate(1);returnpb;}
输出结果:
Java代码
remycannotsetRateremy2
到此,关于“Java动态代理模式怎么实现”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!